Skip to content

Commit 0e2ee97

Browse files
committed
Fix SIGILL when running ext-interpreter directly
If the external interpreter is dynamically compiled with -fPIC, then the libraries we load must also be compiled with -fPIC. GHC/the debugger determines whether to ask the external interpreter to `LoadArchive` vs. `LoadDLL` based on `iservConfDynamic`. We were accidentally hardcoding this to `False`, so we were always loading static archives for package dependencies (-fno-PIC on Linux), even if the external interpreter was dynamic (-fPIC). Now, we set `iservConfDynamic` to `hostIsDynamic`, since the debugger and ext-interp share the same executable. This didn't trigger on macOS because, for macOS, static archives are always compiled with -fPIC. See Note [Dynamic dependencies for dynamic debugger]
1 parent 72a6dfa commit 0e2ee97

1 file changed

Lines changed: 24 additions & 4 deletions

File tree

haskell-debugger/GHC/Debugger/Monad.hs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ import GHCi.Message (mkPipeFromHandles)
8888
import System.IO (hGetLine, IOMode(..))
8989
import qualified GHC.Linker.Loader as Loader
9090
import GHC.Stack.Annotation
91+
import GHC.Platform.Ways
9192

9293
#if MIN_VERSION_ghc(9,15,0)
9394
import GHC.Data.FastString.Env (emptyFsEnv)
@@ -584,11 +585,12 @@ extInterpFromTerminalProcess port = do
584585
, instExtra = ()
585586
}
586587
conf = IServConfig
587-
{ iservConfProgram = "should never be used"
588+
{ iservConfProgram = "the process is already running, we should never need to run it again"
588589
, iservConfOpts = []
589-
, iservConfProfiled = False
590-
, iservConfDynamic = False
591-
, iservConfHook = Nothing
590+
-- VERY IMPORTANT: See Note [Dynamic dependencies for dynamic debugger]
591+
, iservConfDynamic = hostIsDynamic
592+
, iservConfProfiled = hostIsProfiled
593+
, iservConfHook = Nothing -- it's already running!
592594
, iservConfTrace = pure ()
593595
}
594596

@@ -710,6 +712,24 @@ When launching the external interpreter directly attached to the user's
710712
terminal (via runInTerminal), the handles will indeed be connected to a TTY.
711713
712714
[1] https://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.5/html_node/Buffering-Concepts.html
715+
716+
Note [Dynamic dependencies for dynamic debugger]
717+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
718+
When the external interpreter running the debuggee is a dynamically-linked
719+
program compiled with -fPIC, it is of utmost importance that the libraries we
720+
load (e.g. base, ghc-internal, etc) are ALSO compiled with -fPIC. Otherwise, we
721+
end up with the same SIGILL scenario of Note [Dynamic Debuggee for dynamic debugger].
722+
723+
In #260, we battled with another SIGILL for over a week because of this.
724+
Namely, we forgot to configure the external interpreter's
725+
IServConfig.iservConfDynamic (and had hardcoded it to False!!).
726+
727+
When loading a package to the external interpreter, GHC will consult
728+
`iservConfDynamic` on whether to LoadDLL (dynamic lib) or LoadArchive (static
729+
archive). This setting must definitely match the way in which the external
730+
interpreter was compiled (checked with `hostIsDynamic`, since the external
731+
interpreter and the debugger, while not necessarily the same process, are the
732+
same executable). Ditto for `iservConfProfiled` (with `hostIsProfiled`).
713733
-}
714734
--------------------------------------------------------------------------------
715735

0 commit comments

Comments
 (0)