Author: jlowe Date: Wed Jun 11 22:05:04 2014 New Revision: 1602033 URL: http://svn.apache.org/r1602033 Log: HADOOP-10622. Shell.runCommand can deadlock. Contributed by Gera Shegalov
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Shell.java Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt?rev=1602033&r1=1602032&r2=1602033&view=diff ============================================================================== --- hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt (original) +++ hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt Wed Jun 11 22:05:04 2014 @@ -532,6 +532,8 @@ Release 2.5.0 - UNRELEASED HADOOP-10656. The password keystore file is not picked by LDAP group mapping (brandonli) + HADOOP-10622. Shell.runCommand can deadlock (Gera Shegalov via jlowe) + BREAKDOWN OF HADOOP-10514 SUBTASKS AND RELATED JIRAS HADOOP-10520. Extended attributes definition and FileSystem APIs for Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Shell.java URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Shell.java?rev=1602033&r1=1602032&r2=1602033&view=diff ============================================================================== --- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Shell.java (original) +++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Shell.java Wed Jun 11 22:05:04 2014 @@ -526,12 +526,8 @@ abstract public class Shell { } // wait for the process to finish and check the exit code exitCode = process.waitFor(); - try { - // make sure that the error thread exits - errThread.join(); - } catch (InterruptedException ie) { - LOG.warn("Interrupted while reading the error stream", ie); - } + // make sure that the error thread exits + joinThread(errThread); completed.set(true); //the timeout thread handling //taken care in finally block @@ -560,13 +556,9 @@ abstract public class Shell { } catch (IOException ioe) { LOG.warn("Error while closing the input stream", ioe); } - try { - if (!completed.get()) { - errThread.interrupt(); - errThread.join(); - } - } catch (InterruptedException ie) { - LOG.warn("Interrupted while joining errThread"); + if (!completed.get()) { + errThread.interrupt(); + joinThread(errThread); } try { InputStream stderr = process.getErrorStream(); @@ -581,6 +573,19 @@ abstract public class Shell { } } + private static void joinThread(Thread t) { + while (t.isAlive()) { + try { + t.join(); + } catch (InterruptedException ie) { + if (LOG.isWarnEnabled()) { + LOG.warn("Interrupted while joining on: " + t, ie); + } + t.interrupt(); // propagate interrupt + } + } + } + /** return an array containing the command name & its parameters */ protected abstract String[] getExecString();