Thread overview
Signals
May 27, 2015
Robbin
May 27, 2015
Adam D. Ruppe
May 27, 2015
Robbin
May 27, 2015
ketmar
May 27, 2015
Gary Willoughby
May 27, 2015
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
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
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
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
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.
> 
> 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.

if you are on GNU/Linux, you can use `signalfd` to integrate signal processing in your event loop.