HADOOP-7122. Fix thread leak when shell commands time out. Contributed by Todd Lipcon

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1064403 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Todd Lipcon 2011-01-28 01:12:59 +00:00
parent d2e07d27a5
commit c60feead5e
3 changed files with 48 additions and 2 deletions

View File

@ -457,6 +457,8 @@ Release 0.22.0 - Unreleased
HADOOP-7118. Fix NPE in Configuration.writeXml (todd) HADOOP-7118. Fix NPE in Configuration.writeXml (todd)
HADOOP-7122. Fix thread leak when shell commands time out. (todd)
Release 0.21.1 - Unreleased Release 0.21.1 - Unreleased
IMPROVEMENTS IMPROVEMENTS

View File

@ -205,7 +205,7 @@ abstract public class Shell {
process = builder.start(); process = builder.start();
if (timeOutInterval > 0) { if (timeOutInterval > 0) {
timeOutTimer = new Timer(); timeOutTimer = new Timer("Shell command timeout");
timeoutTimerTask = new ShellTimeoutTimerTask( timeoutTimerTask = new ShellTimeoutTimerTask(
this); this);
//One time scheduling. //One time scheduling.
@ -263,7 +263,7 @@ abstract public class Shell {
} catch (InterruptedException ie) { } catch (InterruptedException ie) {
throw new IOException(ie.toString()); throw new IOException(ie.toString());
} finally { } finally {
if ((timeOutTimer!=null) && !timedOut.get()) { if (timeOutTimer != null) {
timeOutTimer.cancel(); timeOutTimer.cancel();
} }
// close the input stream // close the input stream

View File

@ -24,6 +24,10 @@ import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.Timer;
public class TestShell extends TestCase { public class TestShell extends TestCase {
@ -96,6 +100,46 @@ public class TestShell extends TestCase {
assertTrue("Script didnt not timeout" , shexc.isTimedOut()); assertTrue("Script didnt not timeout" , shexc.isTimedOut());
} }
private static int countTimerThreads() {
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
int count = 0;
ThreadInfo[] infos = threadBean.getThreadInfo(threadBean.getAllThreadIds(), 20);
for (ThreadInfo info : infos) {
if (info == null) continue;
for (StackTraceElement elem : info.getStackTrace()) {
if (elem.getClassName().contains("Timer")) {
count++;
break;
}
}
}
return count;
}
public void testShellCommandTimerLeak() throws Exception {
String quickCommand[] = new String[] {"/bin/sleep", "100"};
int timersBefore = countTimerThreads();
System.err.println("before: " + timersBefore);
for (int i = 0; i < 10; i++) {
Shell.ShellCommandExecutor shexec = new Shell.ShellCommandExecutor(
quickCommand, null, null, 1);
try {
shexec.execute();
fail("Bad command should throw exception");
} catch (Exception e) {
// expected
}
}
Thread.sleep(1000);
int timersAfter = countTimerThreads();
System.err.println("after: " + timersAfter);
assertEquals(timersBefore, timersAfter);
}
private void testInterval(long interval) throws IOException { private void testInterval(long interval) throws IOException {
Command command = new Command(interval); Command command = new Command(interval);