SIGINT, longjmp, getaddrinfo
Michael Kerrisk
mtk.manpages@gmail.com
Tue Feb 16 15:00:00 GMT 2016
On Tue, Feb 16, 2016 at 4:11 AM, Hal Murray <hmurray@megapathdsl.net> wrote:
> Thanks for all the replies.
>
>
> carlos@systemhalted.org said:
>> To reiterate: After jumping out of an AS handler you may only call AS-safe
>> functions.
>
> There is no hint of that in my man page for longjmp/siglongjmp. (Most Linux
> distros have the same page from 2009-01-13.)
>
> It does say:
> longjmp() and siglongjmp() make programs hard to understand and main-
> tain. If possible, an alternative should be used.
>
> but I didn't interpret "hard to understand" as hinting at the sorts of
> problems I encountered.
Agreed. That text doesn't really apply to your point. Unfortunately,
the man page was silent on this issue (though I was aware of it).
>
> The NetBSD man page does have an interesting CAVEAT:
> Use of longjmp() or siglongjmp() from inside a signal handler is not as
> easy as it might seem. Generally speaking, all possible code paths
> between the setjmp() and longjmp() must be signal race safe.
> Furthermore, the code paths must not do resource management (such as
> open(2) or close(2)) without blocking the signal in question, or
> resources might be mismanaged. Obviously this makes longjmp() much less
> useful than previously thought.
>
>
> [maybe some routines mask or intercept signals or ...]
> carlos@systemhalted.org said:
>> No code protects against signals like this. It would cause very large signal
>> handling latency e.g. your signal would be pending for a long time while the
>> various library routines finish.
>
> readline installs its own signal handlers. The man page doesn't mention it,
> but a break at sigprocmask shows it getting called from rl_set_signals and
> google finds
> 2.5 Readline Signal Handling
> http://www.delorie.com/gnu/docs/readline/rlman_43.html
>
> carlos@systemhalted.org said:
>> Alternatively use threads and pthread_cancel.
>
> That's the cleanest suggestion I've seen so far.
>
>
> godmar@gmail.com said:
>>> To reiterate: After jumping out of an AS handler you may only call
>>> AS-safe functions.
>> That's not always true in my opinion. It's true only if the main code was
>> able to enter any C library function that is not AS-safe.
>
> The man pages for many routines have a section on thread safety. I don't
> remember ever seeing one on AS safety.
Yep, it is a lack in the man pages generally. But there is a list of
non-async-signal-safe function sin signal(7).
>
>
> godmar@gmail.com said:
>> Personally, though, I agree that the global flag approach will likely be
>> better.
>
> What does something like getnameinfo do when it gets an EINTR while waiting
> for a packet to arrive?
>
> How does it know that a SIGINT handler set a flag and wants to bail as
> compared to a timer went off and it should continue.
>
> ---------------
>
> I poked around some more. I think longjmp-ing out of getnameinfo is leaving
> SIGINT masked. Is that surprising? or reasonable? A break at sigprocmask
> found the readline stuff mentioned above but nothing from getnameinfo. If
> it's interesting, I'll try to put together a simple test program.
>
>
> I'm still surprised that there isn't some web page that documents and
> discusses this whole area.
<Blush> Well, I know there's a book that covers it...
And now I've added this text to the completely revamped setjmp(2) man page[1]:
POSIX.1-2008 Technical Corrigendum 2 adds longjmp() and sig‐
longjmp() to the list of async-signal-safe functions. However,
the standard recommends avoiding the use of these functions from
signal handlers and goes on to point out that if these functions
are called from a signal handler that interrupted a call to a
non-async-signal-safe function (or some equivalent, such as the
steps equivalent to exit(3) that occur upon a return from the
initial call to main()), the behavior is undefined if the program
subsequently makes a call to a non-async-signal-safe. The only
way of avoiding undefined behavior is to ensure one of the fol‐
lowing:
* After long jumping from the signal handler, the program does
not call any non-async-signal-safe functions and does not
return from the initial call to main().
* Any signal whose handler performs a long jump must be blocked
during every call to a non-async-signal-safe function and no
non-async-signal-safe functions are called after returning
from the initial call to main().
Hopefully that covers everyone's concerns.
Cheers,
Michael
[1] http://git.kernel.org/cgit/docs/man-pages/man-pages.git
More information about the Libc-help
mailing list