diff --git a/hadoop-mapreduce-project/CHANGES.txt b/hadoop-mapreduce-project/CHANGES.txt index 44ee434d251..cef1447751e 100644 --- a/hadoop-mapreduce-project/CHANGES.txt +++ b/hadoop-mapreduce-project/CHANGES.txt @@ -352,6 +352,9 @@ Release 0.23.1 - Unreleased MAPREDUCE-3588. Fixed bin/yarn which was broken by MAPREDUCE-3366 so that yarn daemons can start. (Arun C Murthy via vinodkv) + MAPREDUCE-3586. Modified CompositeService to avoid duplicate stop operations + thereby solving race conditions in MR AM shutdown. (vinodkv) + Release 0.23.0 - 2011-11-01 INCOMPATIBLE CHANGES diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/service/CompositeService.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/service/CompositeService.java index 36fecc38ff8..00cebcfef46 100644 --- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/service/CompositeService.java +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/service/CompositeService.java @@ -81,6 +81,10 @@ public class CompositeService extends AbstractService { } public synchronized void stop() { + if (this.getServiceState() == STATE.STOPPED) { + // The base composite-service is already stopped, don't do anything again. + return; + } if (serviceList.size() > 0) { stop(serviceList.size() - 1); } diff --git a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/TestCompositeService.java b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/TestCompositeService.java index 9ca0e4b42c9..7a8aef88f7d 100644 --- a/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/TestCompositeService.java +++ b/hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/TestCompositeService.java @@ -88,6 +88,14 @@ public class TestCompositeService { ((NUM_OF_SERVICES - 1) - i), services[i].getCallSequenceNumber()); } + // Try to stop again. This should be a no-op. + serviceManager.stop(); + // Verify that stop() call sequence numbers for every service don't change. + for (int i = 0; i < NUM_OF_SERVICES; i++) { + assertEquals("For " + services[i] + + " service, stop() call sequence number should have been ", + ((NUM_OF_SERVICES - 1) - i), services[i].getCallSequenceNumber()); + } } @Test @@ -153,7 +161,7 @@ public class TestCompositeService { serviceManager.start(); - // Start the composite service + // Stop the composite service try { serviceManager.stop(); } catch (YarnException e) {