You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by to...@apache.org on 2011/01/28 02:14:15 UTC

svn commit: r1064404 - in /hadoop/common/branches/branch-0.22: CHANGES.txt src/java/org/apache/hadoop/util/Shell.java src/test/core/org/apache/hadoop/util/TestShell.java

Author: todd
Date: Fri Jan 28 01:14:15 2011
New Revision: 1064404

URL: http://svn.apache.org/viewvc?rev=1064404&view=rev
Log:
HADOOP-7122. Fix thread leak when shell commands time out. Contributed by Todd Lipcon

Modified:
    hadoop/common/branches/branch-0.22/CHANGES.txt
    hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/util/Shell.java
    hadoop/common/branches/branch-0.22/src/test/core/org/apache/hadoop/util/TestShell.java

Modified: hadoop/common/branches/branch-0.22/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.22/CHANGES.txt?rev=1064404&r1=1064403&r2=1064404&view=diff
==============================================================================
--- hadoop/common/branches/branch-0.22/CHANGES.txt (original)
+++ hadoop/common/branches/branch-0.22/CHANGES.txt Fri Jan 28 01:14:15 2011
@@ -398,6 +398,8 @@ Release 0.22.0 - Unreleased
 
     HADOOP-7118. Fix NPE in Configuration.writeXml (todd)
 
+    HADOOP-7122. Fix thread leak when shell commands time out. (todd)
+
 Release 0.21.1 - Unreleased
 
   IMPROVEMENTS

Modified: hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/util/Shell.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/util/Shell.java?rev=1064404&r1=1064403&r2=1064404&view=diff
==============================================================================
--- hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/util/Shell.java (original)
+++ hadoop/common/branches/branch-0.22/src/java/org/apache/hadoop/util/Shell.java Fri Jan 28 01:14:15 2011
@@ -200,7 +200,7 @@ abstract public class Shell {
     
     process = builder.start();
     if (timeOutInterval > 0) {
-      timeOutTimer = new Timer();
+      timeOutTimer = new Timer("Shell command timeout");
       timeoutTimerTask = new ShellTimeoutTimerTask(
           this);
       //One time scheduling.
@@ -258,7 +258,7 @@ abstract public class Shell {
     } catch (InterruptedException ie) {
       throw new IOException(ie.toString());
     } finally {
-      if ((timeOutTimer!=null) && !timedOut.get()) {
+      if (timeOutTimer != null) {
         timeOutTimer.cancel();
       }
       // close the input stream

Modified: hadoop/common/branches/branch-0.22/src/test/core/org/apache/hadoop/util/TestShell.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-0.22/src/test/core/org/apache/hadoop/util/TestShell.java?rev=1064404&r1=1064403&r2=1064404&view=diff
==============================================================================
--- hadoop/common/branches/branch-0.22/src/test/core/org/apache/hadoop/util/TestShell.java (original)
+++ hadoop/common/branches/branch-0.22/src/test/core/org/apache/hadoop/util/TestShell.java Fri Jan 28 01:14:15 2011
@@ -24,6 +24,10 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 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 {
 
@@ -95,6 +99,46 @@ public class TestShell extends TestCase 
     shellFile.delete();
     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 {
     Command command = new Command(interval);