c++ - start-stop-daemon not sending SIGTERM -
i have simple daemon boils down to
#include <unistd.h> #include <signal.h> #include <sys/stat.h> #include <fstream> #include <iostream> #include <boost/thread.hpp> bool running = true; std::ofstream log_output; void close_log_output() { log_output.close(); } void signal_handler(int) { running = false; } int detach_service() { if(pid_t pid = fork()) exit(pid < 0); umask(0); close(stdin_fileno); close(stdout_fileno); close(stderr_fileno); chdir("/"); log_output.open("/var/log/mydaemon.log"); std::cout.rdbuf(log_output.rdbuf()); std::cerr.rdbuf(log_output.rdbuf()); std::clog.rdbuf(log_output.rdbuf()); atexit(&close_log_output); signal(sigterm, &signal_handler); return (setsid() < 0); } int main(int argc, char **argv) { if(int err = detach_service()) return err; while(running) boost::this_thread::sleep(boost::posix_time::milliseconds(30)); std::cout << "terminated\n"; return 0; }
and init.d script original skeleton $name
, $daemon
, $daemon_args
adjusted. if kill process via it's pid receives sigterm , terminates properly, if try stop service (which set send term first default) command hangs , process killed without ever receiving sigterm.
what have do/change process terminated correctly (either on shell side or on c++ side)
the modified skeleton (only name , daemon_args changed in comparison original ubuntu init.d skeleton):
#! /bin/sh ### begin init info # provides: skeleton # required-start: $remote_fs $syslog # required-stop: $remote_fs $syslog # default-start: 2 3 4 5 # default-stop: 0 1 6 # short-description: example initscript # description: file should used construct scripts # placed in /etc/init.d. ### end init info # author: foo bar <foobar@baz.org> # # please remove "author" lines above , replace them # own name if copy , modify script. # not "set -e" # path should include /usr/* if runs after mountnfs.sh script path=/sbin:/usr/sbin:/bin:/usr/bin desc="description of service" name=mydaemon daemon=/usr/sbin/$name daemon_args="" pidfile=/var/run/$name.pid scriptname=/etc/init.d/$name # exit if package not installed [ -x "$daemon" ] || exit 0 # read configuration variable file if present [ -r /etc/default/$name ] && . /etc/default/$name # load verbose setting , other rcs variables . /lib/init/vars.sh # define lsb log_* functions. # depend on lsb-base (>= 3.2-14) ensure file present # , status_of_proc working. . /lib/lsb/init-functions # # function starts daemon/service # do_start() { # return # 0 if daemon has been started # 1 if daemon running # 2 if daemon not started start-stop-daemon --start --quiet --pidfile $pidfile --exec $daemon --test > /dev/null \ || return 1 start-stop-daemon --start --quiet --pidfile $pidfile --exec $daemon -- \ $daemon_args \ || return 2 # add code here, if necessary, waits process ready # handle requests services started subsequently depend # on one. last resort, sleep time. } # # function stops daemon/service # do_stop() { # return # 0 if daemon has been stopped # 1 if daemon stopped # 2 if daemon not stopped # other if failure occurred start-stop-daemon --stop --quiet --retry=term/30/kill/5 --pidfile $pidfile --name $name retval="$?" [ "$retval" = 2 ] && return 2 # wait children finish if daemon forks # , if daemon ever run initscript. # if above conditions not satisfied add other code # waits process drop resources # needed services started subsequently. last resort # sleep time. start-stop-daemon --stop --quiet --oknodo --retry=0/30/kill/5 --exec $daemon [ "$?" = 2 ] && return 2 # many daemons don't delete pidfiles when exit. rm -f $pidfile return "$retval" } # # function sends sighup daemon/service # do_reload() { # # if daemon can reload configuration without # restarting (for example, when sent sighup), # implement here. # start-stop-daemon --stop --signal 1 --quiet --pidfile $pidfile --name $name return 0 } case "$1" in start) [ "$verbose" != no ] && log_daemon_msg "starting $desc" "$name" do_start case "$?" in 0|1) [ "$verbose" != no ] && log_end_msg 0 ;; 2) [ "$verbose" != no ] && log_end_msg 1 ;; esac ;; stop) [ "$verbose" != no ] && log_daemon_msg "stopping $desc" "$name" do_stop case "$?" in 0|1) [ "$verbose" != no ] && log_end_msg 0 ;; 2) [ "$verbose" != no ] && log_end_msg 1 ;; esac ;; status) status_of_proc "$daemon" "$name" && exit 0 || exit $? ;; #reload|force-reload) # # if do_reload() not implemented leave commented out # , leave 'force-reload' alias 'restart'. # #log_daemon_msg "reloading $desc" "$name" #do_reload #log_end_msg $? #;; restart|force-reload) # # if "reload" option implemented remove # 'force-reload' alias # log_daemon_msg "restarting $desc" "$name" do_stop case "$?" in 0|1) do_start case "$?" in 0) log_end_msg 0 ;; 1) log_end_msg 1 ;; # old process still running *) log_end_msg 1 ;; # failed start esac ;; *) # failed stop log_end_msg 1 ;; esac ;; *) #echo "usage: $scriptname {start|stop|restart|reload|force-reload}" >&2 echo "usage: $scriptname {start|stop|status|restart|force-reload}" >&2 exit 3 ;; esac :
your daemon not create pidfile, , neither start-stop-daemon
. guess first line
start-stop-daemon --stop --quiet --retry=term/30/kill/5 --pidfile $pidfile --name $name
does nothing, because --pidfile
process selection criterion never satisfied, second line
start-stop-daemon --stop --quiet --oknodo --retry=0/30/kill/5 --exec $daemon
kills daemon sigkill
, because here --pidfile
option not included.
you should fix daemon create pidfile.
Comments
Post a Comment