obelisk
obelisk copied to clipboard
ob run: Child processes are orphaned on SIGHUP
(On Linux,) when terminating ob run
with SIGHUP - e.g. because your terminal is being closed - the child ghcid
process stays alive, and keeps the port occupied. Repro is essentially:
$ ob run # in basically any obelisk project
[...]
Frontend running on http://localhost:8000/
Then pkill -SIGHUP ob
and verify that ghcid is still running, e.g. with pgrep
or simply by causing a reload and verifying that the frontend is still running/updating:
$ pgrep ghcid
257475
$ pkill -SIGHUP ob
$ pgrep ghcid
257475
I think it'd be more natural for the ghcid process to be terminated when ob run
is killed with SIGHUP, just like it's terminated when ob run
is killed with SIGTERM.
Similar issue: #633
Looking into this some more. (Caveat: I don't know much about process handling.)
Something interesting I noticed in that SIGHUP'ing the ghcid
process rather than the Obelisk process leads to the same behavior, leaving behind a ghc
process like above. Does that mean could be a ghcid
problem?
The runGhcid' function uses
Obelisk.Command.Project.nixShellWithoutPkgs. Inlining
runProcess_` there looks like this:
nixShellWithoutPkgs
:: MonadObelisk m
=> FilePath -- ^ Path to project root
-> Bool -- ^ Should this be a pure shell?
-> Bool -- ^ Should we chdir to the package root in the shell?
-> Map Text FilePath -- ^ Package names mapped to their paths
-> String -- ^ Shell attribute to use (e.g. @"ghc"@, @"ghcjs"@, etc.)
-> Maybe String -- ^ If 'Just' run the given command; otherwise just open the interactive shell
-> m ()
nixShellWithoutPkgs root isPure chdirToRoot packageNamesAndPaths shellAttr command = do
pc <- mkObNixShellProc root isPure chdirToRoot packageNamesAndPaths shellAttr command
bracketOnError
(createProcess pc)
(liftIO . Proc.cleanupProcess)
(\((_, _, _, ph)) -> throwExitCode pc =<< waitForProcess ph)
Changing cleanupProcess
to terminateProcess
or terminating the process in a SIGHUP handler doesn't change the fact that the ghc
process is left:
This is as far as I got before running out of ideas.
(\((_, _, _, ph)) -> do
liftIO $ installHandler 1 (CatchInfo (\_ -> Proc.terminateProcess ph)) Nothing
throwExitCode pc =<< waitForProcess ph)