Skip to content

Commit

Permalink
Unregister stdio filenos from descriptor map, so they don't leak.
Browse files Browse the repository at this point in the history
Fixes #2333.
  • Loading branch information
headius committed Dec 18, 2014
1 parent 467ccfb commit bd79165
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 1 deletion.
5 changes: 5 additions & 0 deletions core/src/main/java/org/jruby/Ruby.java
Expand Up @@ -3223,6 +3223,11 @@ public void tearDown(boolean systemExit) {
getJRubyClassLoader().tearDown(isDebug());
}

// Unregister stdio ChannelDescriptors so they don't leak
ChannelDescriptor.unregisterDescriptor(getFilenoExtMap(0));
ChannelDescriptor.unregisterDescriptor(getFilenoExtMap(1));
ChannelDescriptor.unregisterDescriptor(getFilenoExtMap(2));

if (config.isProfilingEntireRun()) {
// not using logging because it's formatted
ProfileCollection profileCollection = threadService.getMainThread().getContext().getProfileCollection();
Expand Down
7 changes: 6 additions & 1 deletion core/src/main/java/org/jruby/util/io/ChannelDescriptor.java
Expand Up @@ -48,6 +48,7 @@
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
Expand Down Expand Up @@ -863,13 +864,17 @@ private static void registerDescriptor(ChannelDescriptor descriptor) {
filenoDescriptorMap.put(descriptor.getFileno(), descriptor);
}

private static void unregisterDescriptor(int aFileno) {
public static void unregisterDescriptor(int aFileno) {
filenoDescriptorMap.remove(aFileno);
}

public static ChannelDescriptor getDescriptorByFileno(int aFileno) {
return filenoDescriptorMap.get(aFileno);
}

public static Map<Integer, ChannelDescriptor> getFilenoDescriptorMapReadOnly() {
return Collections.unmodifiableMap(filenoDescriptorMap);
}

private static final Map<Integer, ChannelDescriptor> filenoDescriptorMap = new ConcurrentHashMap<Integer, ChannelDescriptor>();

Expand Down
13 changes: 13 additions & 0 deletions core/src/test/java/org/jruby/embed/ScriptingContainerTest.java
Expand Up @@ -72,6 +72,7 @@
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ClassCache;
import org.jruby.util.KCode;
import org.jruby.util.io.ChannelDescriptor;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
Expand Down Expand Up @@ -2757,4 +2758,16 @@ public void testClasspathScriptletHasClasspathFile() {
Object result = instance.runScriptlet(PathType.CLASSPATH, "__FILE__.rb");
assertEquals("classpath:/__FILE__.rb", result.toString());
}

@Test
public void testContainerScrubsStdioDescriptors() {
Map<Integer, ChannelDescriptor> orig = ChannelDescriptor.getFilenoDescriptorMapReadOnly();

ScriptingContainer instance = new ScriptingContainer(LocalContextScope.SINGLETHREAD);
instance.runScriptlet("1");

instance.terminate();

assertEquals(orig, ChannelDescriptor.getFilenoDescriptorMapReadOnly());
}
}

0 comments on commit bd79165

Please sign in to comment.