Question

I have a daemon running on Ubuntu written in Perl, it is now single threaded. When it starts up it does the usual Proc::Daemon stuff and then goes into a while loop bounded by a boolean. The daemon starts up fine with "service daemon start". But when I want to kill it with "service daemon stop" it doesn't stop.

Stopping is supposed to happen by flipping the boolean using a signal handler:

$SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&signalHandler;

sub signalHandler {
    $continue = 0;
}

Unfortunately the main loop also has a sleep in it. So the daemon doesn't end until the sleep is over. I would like the daemon to end immediately. But I don't want to set a very low sleep time. In fact I want to be able to set a sleep time of several hours if that is what it determines it should do.

What is the best way to do this?

I was thinking about calling some sort of blocking function inside the main loop instead of a sleep. This blocking function would not return until some thread has died. Then in the signal handler I would simply kill that sleeping thread. Is this a good approach? And how would I do that, I've never done multi-threading in Perl before.

thanks for any help

Was it helpful?

Solution 2

You can move any shutdown-related cleanup to its own subroutine, if you haven't already done so, and let signalHandler() call that cleanup sub and then simply exit. Then edit your start/stop script to send SIGALRM instead. SIGALRM will interupt the sleep. If your script is edited to catch this, everything will be stopped at once.

Further reading: sleep()

OTHER TIPS

Here's a workaround for this situation:

1. Create a named pipe when your software starts running, with, e.g. mkfifo

2. Replace the sleep call with a select system call (as an alternative you can use the perl package IO::Select instead of the select system call).

Set up the select to monitor when the pipe is ready for input.

select allows the specification of a timeout, just like sleep.

The select call returns when either the timeout elapses OR the file condition is met.

3. If the timeout occurs, run your loop's body code. If data appears on the pipe, terminate.

4. To terminate, send data to the named pipe.

Unless you've done something odd to change it, the sleep() function should wake up early and return immediately when a signal is received. You can then change your loop to check the $continue flag after every sleep, to see if you received your shutdown signal.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top