Skip to content

Commit 6f2e150

Browse files
authored
Merge pull request #10 from denibertovic/master
Adds ability to only SIGTERM the immediate process
2 parents 0ebece9 + db9fa58 commit 6f2e150

File tree

3 files changed

+28
-7
lines changed

3 files changed

+28
-7
lines changed

README.md

+9
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ Where:
3434
* `-w`, `--workdir` `DIR` - chdir to `DIR` before executing COMMAND
3535
* `-t`, `--timeout` `TIMEOUT` - timeout (in seconds) to wait for all child processes to exit
3636

37+
`WARNING`: by default pid1 will first send the TERM signal to it's "immediate child" process.
38+
In most scenarios that will be the only process running but in some cases that will be the
39+
"main" process that could have spawned it's own children. In this scenario it's prudent to shutdown
40+
the "main" process first, since usually it has mechanisms in place to shut down it's children. If
41+
we were to shutdown a child process before "main" was shutdown it might try to restart it.
42+
This is why, if the "main" process doesn't exit within `timeout` we will proceed to send the TERM
43+
signal to all processes and wait **again** for `timeout` until we finally send the KILL signal to all
44+
processes. This is a **breaking change since 0.1.3.0**.
45+
3746
The recommended use case for this executable is to embed it in a Docker image.
3847
Assuming you've placed it at `/sbin/pid1`, the two commonly recommended usages
3948
are:

pid1.cabal

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: pid1
2-
version: 0.1.2.0
2+
version: 0.1.3.0
33
synopsis: Do signal handling and orphan reaping for Unix PID1 init processes
44
description: Please see README.md or view Haddocks at <https://www.stackage.org/package/pid1>
55
homepage: https://github.com/fpco/pid1#readme

src/System/Process/PID1.hs

+18-6
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,6 @@ runAsPID1 cmd args env' timeout = do
181181
-- children processes. Then start a thread waiting for that
182182
-- variable to be filled and do the actual killing.
183183
killChildrenVar <- newEmptyMVar
184-
_ <- forkIO $ do
185-
takeMVar killChildrenVar
186-
killAllChildren timeout
187184

188185
-- Helper function to start killing, used below
189186
let startKilling = void $ tryPutMVar killChildrenVar ()
@@ -206,6 +203,10 @@ runAsPID1 cmd args env' timeout = do
206203
ClosedHandle e -> assert False (exitWith e)
207204
OpenHandle pid -> return pid
208205

206+
_ <- forkIO $ do
207+
takeMVar killChildrenVar
208+
killAllChildren child timeout
209+
209210
-- Loop on reaping child processes
210211
reap startKilling child
211212

@@ -247,9 +248,20 @@ reap startKilling child = do
247248
startKilling
248249
| otherwise -> return ()
249250

250-
killAllChildren :: Int -> IO ()
251-
killAllChildren timeout = do
252-
-- Send all children processes the TERM signal
251+
killAllChildren :: CPid -> Int -> IO ()
252+
killAllChildren cid timeout = do
253+
-- Send the direct child process the TERM signal
254+
signalProcess sigTERM cid `catch` \e ->
255+
if isDoesNotExistError e
256+
then return ()
257+
else throwIO e
258+
259+
-- Wait for `timeout` seconds and allow the 'main' process to take care
260+
-- of shutting down any child processes itself.
261+
threadDelay $ timeout * 1000 * 1000
262+
263+
-- If the 'main' process did not handle shutting down the rest of the
264+
-- child processes we will signal SIGTERM to them directly.
253265
signalProcess sigTERM (-1) `catch` \e ->
254266
if isDoesNotExistError e
255267
then return ()

0 commit comments

Comments
 (0)