propagate signals to the transferrer process group

Done on unix, could not implement it on windows quite.

The signal library gets part of the way needed for windows.
But I had to open https://github.com/pmlodawski/signal/issues/1 because
it lacks raiseSignal.

Also, I don't know what the equivilant of getProcessGroupIDOf is on
windows. And System.Process does not provide a way to send any signal to
a process group except for SIGINT.

This commit was sponsored by Boyd Stephen Smith Jr. on Patreon.
This commit is contained in:
Joey Hess 2020-12-11 15:28:58 -04:00
parent 79c765b727
commit d3f78da0ed
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
17 changed files with 150 additions and 48 deletions

View file

@ -5,6 +5,8 @@
- Licensed under the GNU AGPL version 3 or higher.
-}
{-# LANGUAGE CPP #-}
module Annex.Action (
action,
verifiedAction,
@ -25,6 +27,11 @@ import Annex.HashObject
import Annex.CheckIgnore
import Annex.TransferrerPool
import Control.Concurrent.STM
#ifndef mingw32_HOST_OS
import System.Posix.Signals
#endif
{- Runs an action that may throw exceptions, catching and displaying them. -}
action :: Annex () -> Annex Bool
action a = tryNonAsync a >>= \case
@ -43,13 +50,36 @@ verifiedAction a = tryNonAsync a >>= \case
{- Actions to perform each time ran. -}
startup :: Annex ()
startup = return ()
startup = do
#ifndef mingw32_HOST_OS
av <- Annex.getState Annex.signalactions
let propagate sig = liftIO $ installhandleronce sig av
propagate sigINT
propagate sigQUIT
propagate sigTERM
propagate sigTSTP
propagate sigCONT
propagate sigHUP
-- sigWINCH is not propagated; it should not be needed,
-- and the concurrent-output library installs its own signal
-- handler for it.
-- sigSTOP and sigKILL cannot be caught, so will not be propagated.
where
installhandleronce sig av = void $
installHandler sig (CatchOnce (gotsignal sig av)) Nothing
gotsignal sig av = do
mapM_ (\a -> a (fromIntegral sig)) =<< atomically (readTVar av)
raiseSignal sig
installhandleronce sig av
#else
return ()
#endif
{- Cleanup actions. -}
shutdown :: Bool -> Annex ()
shutdown nocommit = do
saveState nocommit
sequence_ =<< M.elems <$> Annex.getState Annex.cleanup
sequence_ =<< M.elems <$> Annex.getState Annex.cleanupactions
stopCoProcesses
{- Stops all long-running child processes, including git query processes. -}