UNIX Socket FAQ

A forum for questions and answers about network programming on Linux and all other Unix-like systems

You are not logged in.

  • Index
  • » General
  • » How advisable is it to do socket calls from a signal handler?

#1 2009-05-05 05:23 PM

jfriesne
Administrator
From: California
Registered: 2005-07-06
Posts: 348
Website

Re: How advisable is it to do socket calls from a signal handler?

Hi all,

My program currently uses a signal handler to catch CTRL-C events.  The signal handler simply sets a boolean variable.  The program's main event loop then polls the boolean every second or so, and if it sees that it has been set, it cleans up and exits.

This works, more or less, but it means that my program can never be completely idle, it must always wake up and poll every second, which seems like a wasteful/ugly way to do things.

On another discussion site I saw someone recommend setting up a socket pair, and having the signal handler close one of the sockets.  The main loop would then select() (or poll()) on that socket, and thus be notified when the signal handler had closed the other one.

My question is, will that work reliably?  I had been under the impression that signal handlers weren't allowed to execute socket routines; but perhaps simply closing a socket (or alternatively, send()-ing a byte on it) would be safe enough?

Bonus question:  Windows has a function somewhat similar to signals in its SetConsoleCtrlHandler() function.  Would a similar scheme work there?

Offline

#2 2009-05-05 05:33 PM

i3839
Oddministrator
From: Amsterdam
Registered: 2003-06-07
Posts: 2,231

Re: How advisable is it to do socket calls from a signal handler?

You don't have to wake up and poll, that's what errno == EINTR is for.

Offline

#3 2009-05-05 05:46 PM

jfriesne
Administrator
From: California
Registered: 2005-07-06
Posts: 348
Website

Re: How advisable is it to do socket calls from a signal handler?

i3839;26641 wrote:

You don't have to wake up and poll, that's what errno == EINTR is for.

Hmm... okay, but with that I have these questions:

1) Don't you have to check for EINTR (and handle it consistently) from every single system call in the entire program, or risk 'losing' the interrupt event?  If so, that would be pretty hard to do correctly when you've got lots of different code modules running, many of whom don't know about each other or what needs to be cleaned up.

2) If a system call returns EINTR, how do you know which signal was received?

3) Does EINTR work under Windows?  (I'm guessing, not ;^))

Offline

#4 2009-05-05 08:46 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,829
Website

Re: How advisable is it to do socket calls from a signal handler?

My question is, will that work reliably? I had been under the impression that signal handlers weren't allowed to execute socket routines; but perhaps simply closing a socket (or alternatively, send()-ing a byte on it) would be safe enough?

That should work fine (either closing the socket or sending a byte through it)...  The
only issue you have with signal handlers is the same exact one you have for multiple
threads: dealing with reentrancy...  If it would be acceptable for a separate thread to
close a socket or send data through it to notify you, then it should be fine for a signal
handler to do it, as well...  (If your system runs signal handlers without their own
signal masked, or if you use the same handler to handle multiple signals, then you
might run into possible issues if you start doing something complex, like sending
more than say a byte of data through the pipe/socket...  But, just closing should be
fine in all cases I can think of...  In the case of multiple simultaneous signal handler
calls, the second one would just end up trying to close an already closed FD, which
isn't a huge deal, as long as you don't die on such errors, or something...)

1) Don't you have to check for EINTR (and handle it consistently) from every single system call in the entire program, or risk 'losing' the interrupt event? If so, that would be pretty hard to do correctly when you've got lots of different code modules running, many of whom don't know about each other or what needs to be cleaned up.

Yeah, while you should definitely always handle EINTR on all I/O ops, I wouldn't
really recommend it as a way to handle your situation (as I understand it)...  It might
have come from a different signal than the SIGINT or whatever you're interested in
trapping...  So, you'd still have to set your special bool to check whenver you got
EINTR to make sure it was from your SIGINT handler...  Plus, depending on your
system and how you've set things up, you might not get EINTR at all (ie: if syscalls
are auto-restarting)...

I agree that using a socketpair() (or really all you need is a simple pipe()) is probably
the ideal method here...  As long as you only need to respond to the event from
wherever you do your select() that includes the other end of that socket/pipe...  In
some cases where I've need IMMEDIATE response to SIGINT, I'll deal with it via
use of ugly sigsetjmp() + siglongjmp()...  Ie: do sigsetjmp() somewhere you want
to jump to for the immediate clean-up and exit behavior, then have your signal
handler do a siglongjmp() to it...  Works no matter WHAT you happen to be doing
at the time...  However, if you are typically spending virtually all your run time waiting
in select() anyway, that's probably good enough without needing to resort to ugly
klugery like sig{set,long}jmp()...

Offline

#5 2009-05-06 12:28 AM

i3839
Oddministrator
From: Amsterdam
Registered: 2003-06-07
Posts: 2,231

Re: How advisable is it to do socket calls from a signal handler?

The following interfaces are never restarted after being interrupted by
       a signal handler, regardless of the use of SA_RESTART; they always fail
       with the error EINTR when interrupted by a signal handler:

...cut...

           * File    descriptor    multiplexing   interfaces:   epoll_wait(2),
             epoll_pwait(2), poll(2), ppoll(2), select(2), and pselect(2).

Assuming you have a main loop with one point where you want to do all the
cleanup including exiting the program, just check the flag at that point, just
like you do now. My point was that you don't have to poll the flag because
the system calls that would otherwise sleep forever do return after your
sighandler executed.

As Rob said, you still need to set the flag. (Also because the handler can
run between system calls.)

Offline

#6 2009-05-06 12:39 AM

jfriesne
Administrator
From: California
Registered: 2005-07-06
Posts: 348
Website

Re: How advisable is it to do socket calls from a signal handler?

Thanks for the help guys; I've rewritten my signal handler to send a byte on a socket instead of setting a boolean, and it appears to be working well.

-Jeremy

Offline

#7 2009-05-06 12:35 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,829
Website

Re: How advisable is it to do socket calls from a signal handler?

Fascinating...  I never knew it was impossible for select() (and company) to ever be
auto-restarted...  It makes perfect sense, now that I think about it, though...

Where'd you pull that quote from, i3839?  I'm just curious to see the rest of the list of
non-restartable functions...  I don't see it in my local sigaction man page, which was
the first place I looked for it...

Offline

#8 2009-05-06 01:16 PM

i3839
Oddministrator
From: Amsterdam
Registered: 2003-06-07
Posts: 2,231

Re: How advisable is it to do socket calls from a signal handler?

signal(7).

Offline

#9 2009-05-06 08:13 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,829
Website

Re: How advisable is it to do socket calls from a signal handler?

It must be a newer version of the man page than I have on my system, because
mine doesn't mention it...  I found a copy online, though...

Offline

#10 2017-05-25 10:27 PM

Jason
Guest

Re: How advisable is it to do socket calls from a signal handler?

Using socket calls within signal handlers can overwrite errno global variable.
This can end up masking errors generated in program which was being executed while it encountered the signal.

See below link
https://www.ibm.com/developerworks/linu … index.html

The above article recommends saving and restoring errno in the signal handler.

This comments section in the below page give few more options to work around this problem.
http://250bpm.com/blog:12

  • Index
  • » General
  • » How advisable is it to do socket calls from a signal handler?

Board footer

Powered by FluxBB