www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Signals

reply "Robbin" <dmd churchilllake.com> writes:
I'm writing a daemon in D on linux.  I need to be able to stop 
(kill) it. The traditional C method is a signal handler.  I can 
do this, but I can't figure out how to get the handler to do 
anything to tell the rest of the daemon to quit.

In a C++ handler, I closed the files that were open, removed a 
PID file and exited.  Nothing complicated in the job.  It was 
more complicated in the implementation - I did a longjump from 
the signal handler to execute the cleanup code.

I would love to setup "std.signals" classes and from the 
"core.stdc.signal" signal handler call "std.signals" emit() to 
trigger the "std.signals" observer.

Is there a canonical D way of catching a SIGTERM and unwinding 
everything?

RC
May 27 2015
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
The way I do it is to set a global variable in the signal 
handler, then have the loop watch for it. So like

__gshared bool terminated = false;
extern(C) void handleSigTerm(int) { terminated = true; }

void main() {
     while(!terminated) {
           if(select() < 0)
              if(errno == EINTR) continue; // let the loop check 
the flag again
           // the rest of the stuff
     }

     // do normal cleanup here, and as the functions return
     // naturally they will do unwinding.
}



Of course, with this strategy, if there's some long operation 
running inside the loop it won't get a chance to check the 
flag.... how you handle that is up to you. Maybe check that flag 
from time to time and throw an exception from work functions if 
it is set.


But there's no convenient way to exit from the handler itself 
while doing unwinding. You can exit, sure (use the C exit 
function), and the OS will clean up a lot of stuff but D 
destructors won't be called that way.
May 27 2015
parent reply "Robbin" <dmd churchilllake.com> writes:
I'm using nanomsg to communicate between various components 
(actually distributed across a number of computers) and my main 
event loops are waiting for a message.  The reads are 
encapsulated in a class, so I guess I'll change from a recv to a 
poll and add a second channel to communicate when it is time to 
die.  In the signal handler I can send a message and in the 
class, send a std.signal to end the thread and then clean up the 
main loop and exit.  nn_poll is a c routine, so I should work 
comfortably in the handler.

I wish there was a more direct way to do this.  Signals are a 
bread and butter aspect of the Linux architecture.  I guess 
mangling is at the root of the problem.

Thank you.
May 27 2015
parent ketmar <ketmar ketmar.no-ip.org> writes:
On Wed, 27 May 2015 16:08:28 +0000, Robbin wrote:

 I'm using nanomsg to communicate between various components (actually
 distributed across a number of computers) and my main event loops are
 waiting for a message.  The reads are encapsulated in a class, so I
 guess I'll change from a recv to a poll and add a second channel to
 communicate when it is time to die.  In the signal handler I can send a
 message and in the class, send a std.signal to end the thread and then
 clean up the main loop and exit.  nn_poll is a c routine, so I should
 work comfortably in the handler.
=20
 I wish there was a more direct way to do this.  Signals are a bread and
 butter aspect of the Linux architecture.  I guess mangling is at the
 root of the problem.
=20
 Thank you.
if you are on GNU/Linux, you can use `signalfd` to integrate signal=20 processing in your event loop.=
May 27 2015
prev sibling parent "Gary Willoughby" <dev nomad.so> writes:
On Wednesday, 27 May 2015 at 13:52:33 UTC, Robbin wrote:
 I'm writing a daemon in D on linux.  I need to be able to stop 
 (kill) it. The traditional C method is a signal handler.  I can 
 do this, but I can't figure out how to get the handler to do 
 anything to tell the rest of the daemon to quit.

 In a C++ handler, I closed the files that were open, removed a 
 PID file and exited.  Nothing complicated in the job.  It was 
 more complicated in the implementation - I did a longjump from 
 the signal handler to execute the cleanup code.

 I would love to setup "std.signals" classes and from the 
 "core.stdc.signal" signal handler call "std.signals" emit() to 
 trigger the "std.signals" observer.

 Is there a canonical D way of catching a SIGTERM and unwinding 
 everything?

 RC
I've usually just done this: import core.stdc.stdlib : exit; import core.sys.posix.signal : bsd_signal, SIGTERM; extern(C) void handleTermination(int signal) { // Clean up code here. exit(signal); } bsd_signal(SIGTERM, &handleTermination);
May 27 2015