kill all subprocesses of a daemon

5k Views Asked by At

I am writing an /etc/init.d/mydaemon:

# ...
source functions # LSB compliant 

EXEC=/usr/local/bin/mydaemon
PROG=mydaemon

function start() {
  daemon --pidfile=/var/run/mydeamon.pid ${EXEC}
}

function stop() {
  killproc ${PROG}
}

# ...

my /usr/local/bin/mydaemon:

#!/bin/bash
trap "trap TERM ; kill 0" TERM
binary with some args

AFAIK, this should work because:

  • daemon records the mydaemon's PID in /var/run/mydaemon.pid
  • killproc read that PID and send SIGTERM to that PID.
  • mydaemon trap this signal, disable the trap and send SIGTERM to the entire PGRP, including the process of binary with some args.

However this doesn't work. After stopping the service, mydaemon terminates, but binary is still running.

What am I missing, and what is the best practice for stopping the daemon and all its' children?


BTW:

When my /usr/local/bin/mydaemon is:

#!/bin/bash
binary with some args &
echo $! $$ > /var/run/mydaemon.pid
wait

It works properly, but this seems less robust to me, and there are times where this is not appropriate (when the binary invocation is less straight forward, or it has it's own children, etc).

3

There are 3 best solutions below

0
On

If you give the parent process' id to pkill, it'll kill all the children:

pkill -TERM -P parentID
0
On

You can set up a trap, which takes care of the cleanup process when SIGINT is received. For example:

function cleanup { kill $CHILDPID; exit 0; }
trap cleanup SIGINT SIGTERM

See here for more examples.

0
On

For the specific scenario presented in the question, it is also worth considering the following option for /usr/local/bin/mydaemon:

#!/bin/bash
exec binary with some args

Rather than being run in a subprocess with a new PID, binary will instead take over the shell process PID, and hence receive the signals from the init script directly.