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:
parent
d2e07d27a5
commit
c60feead5e
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
@ -95,6 +99,46 @@ public class TestShell extends TestCase {
|
||||||
shellFile.delete();
|
shellFile.delete();
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue