www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - CTRL-C trapping in Linux

reply James Dunne <jdunne4 bradley.edu> writes:
Hello,

Can we have a platform-independent way to trap the CTRL-C signal for D programs?
I'm writing a server application that needs to close nicely on a CTRL-C under
Linux.

Also, the static ~this() of modules does not get executed on a CTRL-C, and the
garbage collector is left undestroyed (presumably the memory is freed by the OS
upon program close).

A temporary fix would be to define export functions of the signal() routines
under Linux (which are not in the Phobos linux declaration modules, and which
should be) and call them with extern (C) defined signal-handler functions.

Regards,
James Dunne
Feb 07 2005
next sibling parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
Would you want to have some kind of Ctrl-C handler registration, whereby 
an object implementing ICtrlCHandler, or some such, would be passed into 
a registration function. If the user requires, the implementing instance 
would have access to state within the (main) thread of execution, such 
that it could take action?

I've recently used ACE a lot in applications, and I registered a Ctrl-C 
handler that called ACE_Reactor::instance()->end_reactor_event_loop();, 
such that when the user presses Ctrl-C, things get shut down in a nice 
orderly fashion. They even get a polite message on the screen informing 
that shutdown operations are pending. :-)

"James Dunne" <jdunne4 bradley.edu> wrote in message 
news:cu9fgg$28mr$1 digitaldaemon.com...
 Hello,

 Can we have a platform-independent way to trap the CTRL-C signal for D 
 programs?
 I'm writing a server application that needs to close nicely on a 
 CTRL-C under
 Linux.

 Also, the static ~this() of modules does not get executed on a CTRL-C, 
 and the
 garbage collector is left undestroyed (presumably the memory is freed 
 by the OS
 upon program close).

 A temporary fix would be to define export functions of the signal() 
 routines
 under Linux (which are not in the Phobos linux declaration modules, 
 and which
 should be) and call them with extern (C) defined signal-handler 
 functions.

 Regards,
 James Dunne 

Feb 07 2005
parent James Dunne <jdunne4 bradley.edu> writes:
Something like that would be great in D (or phobos)!  However, it could even be
simplified to some special function name like _Dterminate() which would be
automatically registered to handle CTRL-C or other kill signals in dmain.d.
It'd have to be cross-platform too, of course, and handle Windows signals
similarly.

If tempted enough, I might be able to hack out a quick phobos patch for it.

In article <cu9gpv$2cki$1 digitaldaemon.com>, Matthew says...
Would you want to have some kind of Ctrl-C handler registration, whereby 
an object implementing ICtrlCHandler, or some such, would be passed into 
a registration function. If the user requires, the implementing instance 
would have access to state within the (main) thread of execution, such 
that it could take action?

I've recently used ACE a lot in applications, and I registered a Ctrl-C 
handler that called ACE_Reactor::instance()->end_reactor_event_loop();, 
such that when the user presses Ctrl-C, things get shut down in a nice 
orderly fashion. They even get a polite message on the screen informing 
that shutdown operations are pending. :-)

"James Dunne" <jdunne4 bradley.edu> wrote in message 
news:cu9fgg$28mr$1 digitaldaemon.com...
 Hello,

 Can we have a platform-independent way to trap the CTRL-C signal for D 
 programs?
 I'm writing a server application that needs to close nicely on a 
 CTRL-C under
 Linux.

 Also, the static ~this() of modules does not get executed on a CTRL-C, 
 and the
 garbage collector is left undestroyed (presumably the memory is freed 
 by the OS
 upon program close).

 A temporary fix would be to define export functions of the signal() 
 routines
 under Linux (which are not in the Phobos linux declaration modules, 
 and which
 should be) and call them with extern (C) defined signal-handler 
 functions.

 Regards,
 James Dunne 


Regards, James Dunne
Feb 07 2005
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
James Dunne wrote:
 Hello,
 
 Can we have a platform-independent way to trap the CTRL-C signal for D
programs?
 I'm writing a server application that needs to close nicely on a CTRL-C under
 Linux.

As I see it, the simple and logical solution is to have Ctrl+C throw an exception. But how easy or not would this be to implement? I'm guessing it would be similar to having an exception for access violation.... Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Feb 08 2005
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message 
news:cua28q$10ll$1 digitaldaemon.com...
 James Dunne wrote:
 Hello,

 Can we have a platform-independent way to trap the CTRL-C signal for 
 D programs?
 I'm writing a server application that needs to close nicely on a 
 CTRL-C under
 Linux.

As I see it, the simple and logical solution is to have Ctrl+C throw an exception.

Throw it where, or to whom? AFAICR, Ctrl-C is a signal on UNIX, and on Win32 the registered callback is invoked asynchronously. Therefore, a thrown exception is not the answer.
 But how easy or not would this be to implement?  I'm guessing it would 
 be similar to having an exception for access violation....

Feb 08 2005
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Matthew wrote:
 "Stewart Gordon" <smjg_1998 yahoo.com> wrote in message 
 news:cua28q$10ll$1 digitaldaemon.com...

 As I see it, the simple and logical solution is to have Ctrl+C throw 
 an exception.

Throw it where, or to whom?

Where the program counter is at the moment it's pressed. To whatever catches it - exactly the same as with any exception.
 AFAICR, Ctrl-C is a signal on UNIX, and on Win32 the registered callback 
 is invoked asynchronously. Therefore, a thrown exception is not the 
 answer.

Hmm.... Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Feb 08 2005
parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message
news:cua5g0$18ec$1 digitaldaemon.com...
 Matthew wrote:
 "Stewart Gordon" <smjg_1998 yahoo.com> wrote in message
news:cua28q$10ll$1 digitaldaemon.com...

 As I see it, the simple and logical solution is to have Ctrl+C throw an
exception.

Throw it where, or to whom?

Where the program counter is at the moment it's pressed. To whatever catches it - exactly the same as with any exception.

Sorry, mate, but that's just crazy. It'd mean that every bit of code, _everywhere_, would have to be written to be mindful of the possibility of catching such an exception, right down to halfway through reading/writing a 64-bit integer. Not gonna happen.
Feb 08 2005
next sibling parent James Dunne <jdunne4 bradley.edu> writes:
Right, anyway...

It'd be best accomplished with a specialized function as I stated before, that
if defined by the user, is the automatically registered callback for the signal
or the Windows equivalent of such.

In article <cua74c$1dcm$1 digitaldaemon.com>, Matthew says...
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message
news:cua5g0$18ec$1 digitaldaemon.com...
 Matthew wrote:
 "Stewart Gordon" <smjg_1998 yahoo.com> wrote in message
news:cua28q$10ll$1 digitaldaemon.com...

 As I see it, the simple and logical solution is to have Ctrl+C throw an
exception.

Throw it where, or to whom?

Where the program counter is at the moment it's pressed. To whatever catches it - exactly the same as with any exception.

Sorry, mate, but that's just crazy. It'd mean that every bit of code, _everywhere_, would have to be written to be mindful of the possibility of catching such an exception, right down to halfway through reading/writing a 64-bit integer. Not gonna happen.

Regards, James Dunne
Feb 08 2005
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Matthew wrote:
<snip>
 Where the program counter is at the moment it's pressed. To 
 whatever catches it - exactly the same as with any exception.

Sorry, mate, but that's just crazy. It'd mean that every bit of code, _everywhere_, would have to be written to be mindful of the possibility of catching such an exception, right down to halfway through reading/writing a 64-bit integer.

So, what is the conventional means of getting round this, be they Unix, MS-DOS or Windows console apps? Maybe if I knew more about what a signal is.... Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Feb 08 2005
parent reply James Dunne <jdunne4 bradley.edu> writes:
Stewart,

A signal, in Linux (or any POSIX compliant OS) at least, is a special message
that the OS sends to a process on a special event.  You can think of these
signals as sort-of like the Windows message pump idea, if you know how that
works.  Basically, the Linux program sets up signal handling functions for the
different signals it wants to catch.

For example, the most common signals to trap are SIGTERM and SIGINT.  SIGTERM is
a signal sent when the OS needs to TERMinate the process (probably on system
shutdown, or via the kill shell command).  The other signal, SIGINT, is the
signal sent when the user sends a CTRL-C to the process from the shell.  It is
useful to trap this signal in order to shut down programs properly.

As of right now, D offers no protection to CTRL-C signals, or SIGTERM signals in
Linux or their equivalents on Windows.  This means that if you CTRL-C or kill a
D program, the static module and class destructors will not be called and the GC
will not be properly terminated, which is a Bad Thing (TM).

I've written a simple Linux-only signal trapper which will shut down the program
correctly and call the static destructors and terminate the GC.  I'm sure
there's a way to do this similarly in Windows (probably with the _atexit
function, but I'm not sure about that), but in my selfishness, I don't need
Windows support for that feature right now, so I didn't bother with it. ;)

If more people are interested, I can hack up a nice phobos patch for this
almost-necessary feature!


Here's an example with code:

#import	std.c.stdlib;
#version (linux) import std.c.linux.linux;
#
#// On my machine, this was thrown in at the end of std.c.linux.linuxextern:
#typedef void (*sighandler_t)(int);
#extern (C) sighandler_t signal(int signal, sighandler_t handler);
#
#// These are for control of termination:
#extern (C) void _STD_monitor_staticdtor();
#extern (C) void _STD_critical_term();
#extern (C) void gc_term();
#extern (C) void _moduleDtor();
#
#// Called upon a signal from Linux
#extern (C) void sighandler(int sig) {
#	printf("signal %d caught...\n", sig);
#	terminate();
#}
#
#void terminate() {
#	// Place your own custom shutdown code here!
#
#	// D termination (since we can't really make main() return):
#	_moduleDtor();
#	gc_term();
#	version (linux) {
#		//free(am);
#		_STD_critical_term();
#		_STD_monitor_staticdtor();
#	}
#
#	exit(0);
#}
#
#int main(char[][] args) {
#	// Register the SIGINT signal with the sighandler function call:
#	version (linux) {
#		signal(SIGABRT, &sighandler);
#		signal(SIGTERM, &sighandler);
#		signal(SIGQUIT, &sighandler);
#		signal(SIGINT, &sighandler);
#	}
#
#	try {
#		// Do your main loop code here...
#	} catch (Exception e) {
#		e.print();
#	} finally {
#		// Call your terminate() function to properly terminate the program:
#		terminate();
#	}
#
#	// Don't rely on returning from main if you have custom shutdown code in
terminate():
#	return 0;
#}

In article <cuaq7a$307i$1 digitaldaemon.com>, Stewart Gordon says...
Matthew wrote:
<snip>
 Where the program counter is at the moment it's pressed. To 
 whatever catches it - exactly the same as with any exception.

Sorry, mate, but that's just crazy. It'd mean that every bit of code, _everywhere_, would have to be written to be mindful of the possibility of catching such an exception, right down to halfway through reading/writing a 64-bit integer.

So, what is the conventional means of getting round this, be they Unix, MS-DOS or Windows console apps? Maybe if I knew more about what a signal is.... Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.

Regards, James Dunne
Feb 08 2005
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
James Dunne wrote:
 Stewart,
 
 A signal, in Linux (or any POSIX compliant OS) at least, is a special message
 that the OS sends to a process on a special event.  You can think of these
 signals as sort-of like the Windows message pump idea, if you know how that
 works.  Basically, the Linux program sets up signal handling functions for the
 different signals it wants to catch.
 
 For example, the most common signals to trap are SIGTERM and SIGINT.  SIGTERM
is
 a signal sent when the OS needs to TERMinate the process (probably on system
 shutdown, or via the kill shell command).  The other signal, SIGINT, is the
 signal sent when the user sends a CTRL-C to the process from the shell.  It is
 useful to trap this signal in order to shut down programs properly.

I see. But doesn't that carry the same risk of being interrupted halfway through reading a 64-bit integer that Matthew mentioned? Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Feb 11 2005