Index: hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/rm/RMCommunicator.java =================================================================== --- hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/rm/RMCommunicator.java (revision 1571927) +++ hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/rm/RMCommunicator.java (working copy) @@ -87,6 +87,7 @@ // Has a signal (SIGTERM etc) been issued? protected volatile boolean isSignalled = false; private volatile boolean shouldUnregister = true; + private volatile boolean isApplicationMasterRegistered = false; public RMCommunicator(ClientService clientService, AppContext context) { super("RMCommunicator"); @@ -153,6 +154,7 @@ } RegisterApplicationMasterResponse response = scheduler.registerApplicationMaster(request); + setApplicationMasterRegistered(true); maxContainerCapability = response.getMaximumResourceCapability(); this.context.getClusterInfo().setMaxContainerCapability( maxContainerCapability); @@ -249,7 +251,7 @@ LOG.warn("InterruptedException while stopping", ie); } } - if(shouldUnregister) { + if (hasApplicationMasterRegistered() && shouldUnregister) { unregister(); } super.serviceStop(); @@ -328,4 +330,12 @@ LOG.info("RMCommunicator notified that iSignalled is: " + isSignalled); } + + public boolean hasApplicationMasterRegistered() { + return isApplicationMasterRegistered; + } + + public boolean setApplicationMasterRegistered(boolean isRegistered) { + return this.isApplicationMasterRegistered = isRegistered; + } } Index: hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/TestJobEndNotifier.java =================================================================== --- hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/TestJobEndNotifier.java (revision 1571927) +++ hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/v2/app/TestJobEndNotifier.java (working copy) @@ -219,8 +219,45 @@ JobEndServlet.foundJobState); server.stop(); } + + @Test + public void testUnregistrationOnlyIfRegistered() throws Exception { + HttpServer2 server = startHttpServer(); + MRApp app = + spy(new MRAppWithCustomContainerAllocator(1, 1, true, this.getClass() + .getName(), true, 2, true)); + doNothing().when(app).sysexit(); + JobConf conf = new JobConf(); + app.init(conf); + Assert.assertFalse(((RMCommunicator) app.getContainerAllocator()) + .hasApplicationMasterRegistered()); + // Call shutdown before registering. + app.stop(); + Assert.assertFalse(app.successfullyUnregistered.get()); + app.shutDownJob(); + server.stop(); + } @Test + public void testRegistrationAndUnregistration() throws Exception { + HttpServer2 server = startHttpServer(); + MRApp app = + spy(new MRAppWithCustomContainerAllocator(1, 1, true, this.getClass() + .getName(), true, 2, true)); + doNothing().when(app).sysexit(); + JobConf conf = new JobConf(); + conf.set(JobContext.MR_JOB_END_NOTIFICATION_URL, JobEndServlet.baseUrl + + "jobend?jobid=$jobId&status=$jobStatus"); + JobImpl job = (JobImpl) app.submit(conf); + app.waitForInternalState(job, JobStateInternal.SUCCEEDED); + Assert.assertTrue(((RMCommunicator) app.getContainerAllocator()) + .hasApplicationMasterRegistered()); + Assert.assertTrue(app.successfullyUnregistered.get()); + app.shutDownJob(); + server.stop(); + } + + @Test public void testAbsentNotificationOnNotLastRetryUnregistrationFailure() throws Exception { HttpServer2 server = startHttpServer(); @@ -357,12 +394,20 @@ @Override public void serviceStart() { + register(); } @Override public void serviceStop() { - unregister(); + if (hasApplicationMasterRegistered()) { + unregister(); + } } + + @Override + protected void register() { + setApplicationMasterRegistered(true); + } @Override protected void doUnregistration()