From b45df9292a596b15e4e93857611b8702e54e96b9 Mon Sep 17 00:00:00 2001
From: "Edward Z. Yang" <ezyang@cs.stanford.edu>
Date: Mon, 22 Aug 2016 15:28:20 -0700
Subject: [PATCH] Give an explicit message when SIGSEGV happens.

Fixes #767.

Signed-off-by: Edward Z. Yang <ezyang@cs.stanford.edu>
---
 .../Distribution/Client/ProjectBuilding.hs    |  3 +-
 .../Client/ProjectOrchestration.hs            | 29 +++++++++++++++++--
 cabal-install/cabal-install.cabal             |  4 +++
 .../tests/IntegrationTests/custom/segfault.sh | 10 +++++++
 .../IntegrationTests/custom/segfault/Setup.hs |  3 ++
 .../custom/segfault/cabal.project             |  1 +
 .../custom/segfault/plain.cabal               | 14 +++++++++
 7 files changed, 60 insertions(+), 4 deletions(-)
 create mode 100644 cabal-install/tests/IntegrationTests/custom/segfault.sh
 create mode 100644 cabal-install/tests/IntegrationTests/custom/segfault/Setup.hs
 create mode 100644 cabal-install/tests/IntegrationTests/custom/segfault/cabal.project
 create mode 100644 cabal-install/tests/IntegrationTests/custom/segfault/plain.cabal

diff --git a/cabal-install/Distribution/Client/ProjectBuilding.hs b/cabal-install/Distribution/Client/ProjectBuilding.hs
index d2da547998..8ad38b42a0 100644
--- a/cabal-install/Distribution/Client/ProjectBuilding.hs
+++ b/cabal-install/Distribution/Client/ProjectBuilding.hs
@@ -690,7 +690,8 @@ rebuildTargets verbosity
       InstallPlan.execute jobControl keepGoing
                           (BuildFailure Nothing . DependentFailed . packageId)
                           installPlan $ \pkg ->
-        handle (return . Left) $ fmap Right $ --TODO: review exception handling
+        --TODO: review exception handling
+        handle (\(e :: BuildFailure) -> return (Left e)) $ fmap Right $
 
         let uid = installedUnitId pkg
             Just pkgBuildStatus = Map.lookup uid pkgsBuildStatus in
diff --git a/cabal-install/Distribution/Client/ProjectOrchestration.hs b/cabal-install/Distribution/Client/ProjectOrchestration.hs
index bede782e85..6750e9c50c 100644
--- a/cabal-install/Distribution/Client/ProjectOrchestration.hs
+++ b/cabal-install/Distribution/Client/ProjectOrchestration.hs
@@ -93,7 +93,7 @@ import           Data.Either
 import           Control.Exception (Exception(..))
 import           System.Exit (ExitCode(..), exitFailure)
 #ifdef MIN_VERSION_unix
-import           System.Posix.Signals (sigKILL)
+import           System.Posix.Signals (sigKILL, sigSEGV)
 #endif
 
 
@@ -586,11 +586,14 @@ reportBuildFailures verbosity plan buildOutcomes
       | otherwise
       = False
 
+    -- NB: if the Setup script segfaulted or was interrupted,
+    -- we should give more detailed information.  So only
+    -- assume that exit code 1 is "pedestrian failure."
     isFailureSelfExplanatory (BuildFailed e)
-      | Just (ExitFailure _) <- fromException e = True
+      | Just (ExitFailure 1) <- fromException e = True
 
     isFailureSelfExplanatory (ConfigureFailed e)
-      | Just (ExitFailure _) <- fromException e = True
+      | Just (ExitFailure 1) <- fromException e = True
 
     isFailureSelfExplanatory _                  = False
 
@@ -651,7 +654,27 @@ reportBuildFailures verbosity plan buildOutcomes
       Just (ExitFailure 1) -> ""
 
 #ifdef MIN_VERSION_unix
+      -- Note [Positive "signal" exit code]
+      -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+      -- What's the business with the test for negative and positive
+      -- signal values?  The API for process specifies that if the
+      -- process died due to a signal, it returns a *negative* exit
+      -- code.  So that's the negative test.
+      --
+      -- What about the positive test?  Well, when we find out that
+      -- a process died due to a signal, we ourselves exit with that
+      -- exit code.  However, we don't "kill ourselves" with the
+      -- signal; we just exit with the same code as the signal: thus
+      -- the caller sees a *positive* exit code.  So that's what
+      -- happens when we get a positive exit code.
       Just (ExitFailure n)
+        | -n == fromIntegral sigSEGV ->
+            " The build process segfaulted (i.e. SIGSEGV)."
+
+        |  n == fromIntegral sigSEGV ->
+            " The build process terminated with exit code " ++ show n
+         ++ " which may be because some part of it segfaulted. (i.e. SIGSEGV)."
+
         | -n == fromIntegral sigKILL ->
             " The build process was killed (i.e. SIGKILL). " ++ explanation
 
diff --git a/cabal-install/cabal-install.cabal b/cabal-install/cabal-install.cabal
index 7cb6c779a2..efe1faa6af 100644
--- a/cabal-install/cabal-install.cabal
+++ b/cabal-install/cabal-install.cabal
@@ -35,6 +35,10 @@ Extra-Source-Files:
   tests/IntegrationTests/custom/plain/A.hs
   tests/IntegrationTests/custom/plain/Setup.hs
   tests/IntegrationTests/custom/plain/plain.cabal
+  tests/IntegrationTests/custom/segfault.sh
+  tests/IntegrationTests/custom/segfault/Setup.hs
+  tests/IntegrationTests/custom/segfault/cabal.project
+  tests/IntegrationTests/custom/segfault/plain.cabal
   tests/IntegrationTests/exec/Foo.hs
   tests/IntegrationTests/exec/My.hs
   tests/IntegrationTests/exec/adds_sandbox_bin_directory_to_path.out
diff --git a/cabal-install/tests/IntegrationTests/custom/segfault.sh b/cabal-install/tests/IntegrationTests/custom/segfault.sh
new file mode 100644
index 0000000000..a265b579a1
--- /dev/null
+++ b/cabal-install/tests/IntegrationTests/custom/segfault.sh
@@ -0,0 +1,10 @@
+. ./common.sh
+if [ "x$(uname)" != "xLinux" ]; then
+    exit
+fi
+# Older GHCs don't report exit via signal adequately
+require_ghc_ge 708
+cd segfault
+! cabal new-build 2> log
+cat log
+grep SIGSEGV log
diff --git a/cabal-install/tests/IntegrationTests/custom/segfault/Setup.hs b/cabal-install/tests/IntegrationTests/custom/segfault/Setup.hs
new file mode 100644
index 0000000000..5ffb268355
--- /dev/null
+++ b/cabal-install/tests/IntegrationTests/custom/segfault/Setup.hs
@@ -0,0 +1,3 @@
+import System.Posix.Signals
+
+main = putStrLn "Quitting..." >> raiseSignal sigSEGV
diff --git a/cabal-install/tests/IntegrationTests/custom/segfault/cabal.project b/cabal-install/tests/IntegrationTests/custom/segfault/cabal.project
new file mode 100644
index 0000000000..e6fdbadb43
--- /dev/null
+++ b/cabal-install/tests/IntegrationTests/custom/segfault/cabal.project
@@ -0,0 +1 @@
+packages: .
diff --git a/cabal-install/tests/IntegrationTests/custom/segfault/plain.cabal b/cabal-install/tests/IntegrationTests/custom/segfault/plain.cabal
new file mode 100644
index 0000000000..24548713cf
--- /dev/null
+++ b/cabal-install/tests/IntegrationTests/custom/segfault/plain.cabal
@@ -0,0 +1,14 @@
+name:                plain
+version:             0.1.0.0
+license:             BSD3
+author:              Edward Z. Yang
+maintainer:          ezyang@cs.stanford.edu
+build-type:          Custom
+cabal-version:       >=1.10
+
+library
+  build-depends:       base
+  default-language:    Haskell2010
+
+custom-setup
+  setup-depends: base, unix
-- 
GitLab