From e6d18b188143bb8581cf935888cafd7cca59a463 Mon Sep 17 00:00:00 2001
From: Joffrey F <joffrey@docker.com>
Date: Tue, 10 Jul 2018 15:28:55 -0400
Subject: [PATCH] Fix --exit-code-from to reflect exit code after termination
 by Compose

Signed-off-by: Joffrey F <joffrey@docker.com>
---
 compose/cli/main.py          | 53 +++++++++++++++++++-----------------
 tests/acceptance/cli_test.py |  9 ++++++
 2 files changed, 37 insertions(+), 25 deletions(-)

diff --git a/compose/cli/main.py b/compose/cli/main.py
index a97205836..fa6401412 100644
--- a/compose/cli/main.py
+++ b/compose/cli/main.py
@@ -1085,6 +1085,9 @@ class TopLevelCommand(object):
                 )
 
                 self.project.stop(service_names=service_names, timeout=timeout)
+                if exit_value_from:
+                    exit_code = compute_service_exit_code(exit_value_from, attached_containers)
+
                 sys.exit(exit_code)
 
     @classmethod
@@ -1103,33 +1106,33 @@ class TopLevelCommand(object):
             print(get_version_info('full'))
 
 
+def compute_service_exit_code(exit_value_from, attached_containers):
+    candidates = list(filter(
+        lambda c: c.service == exit_value_from,
+        attached_containers))
+    if not candidates:
+        log.error(
+            'No containers matching the spec "{0}" '
+            'were run.'.format(exit_value_from)
+        )
+        return 2
+    if len(candidates) > 1:
+        exit_values = filter(
+            lambda e: e != 0,
+            [c.inspect()['State']['ExitCode'] for c in candidates]
+        )
+
+        return exit_values[0]
+    return candidates[0].inspect()['State']['ExitCode']
+
+
 def compute_exit_code(exit_value_from, attached_containers, cascade_starter, all_containers):
     exit_code = 0
-    if exit_value_from:
-        candidates = list(filter(
-            lambda c: c.service == exit_value_from,
-            attached_containers))
-        if not candidates:
-            log.error(
-                'No containers matching the spec "{0}" '
-                'were run.'.format(exit_value_from)
-            )
-            exit_code = 2
-        elif len(candidates) > 1:
-            exit_values = filter(
-                lambda e: e != 0,
-                [c.inspect()['State']['ExitCode'] for c in candidates]
-            )
-
-            exit_code = exit_values[0]
-        else:
-            exit_code = candidates[0].inspect()['State']['ExitCode']
-    else:
-        for e in all_containers:
-            if (not e.is_running and cascade_starter == e.name):
-                if not e.exit_code == 0:
-                    exit_code = e.exit_code
-                    break
+    for e in all_containers:
+        if (not e.is_running and cascade_starter == e.name):
+            if not e.exit_code == 0:
+                exit_code = e.exit_code
+                break
 
     return exit_code
 
diff --git a/tests/acceptance/cli_test.py b/tests/acceptance/cli_test.py
index 43e8fa822..471b1831a 100644
--- a/tests/acceptance/cli_test.py
+++ b/tests/acceptance/cli_test.py
@@ -2620,6 +2620,15 @@ class CLITestCase(DockerClientTestCase):
 
         assert 'exit-code-from_another_1 exited with code 1' in result.stdout
 
+    def test_exit_code_from_signal_stop(self):
+        self.base_dir = 'tests/fixtures/exit-code-from'
+        proc = start_process(
+            self.base_dir,
+            ['up', '--abort-on-container-exit', '--exit-code-from', 'simple']
+        )
+        result = wait_on_process(proc, returncode=137)  # SIGKILL
+        assert 'exit-code-from_another_1 exited with code 1' in result.stdout
+
     def test_images(self):
         self.project.get_service('simple').create_container()
         result = self.dispatch(['images'])