Discussion:
posix standard question about signal handlers
David Korn
2014-10-13 23:52:26 UTC
Permalink
By default, when a signal handler is invoked, the signal is blocked and
then released when the signal handler completes.

Is there any way in the standard to specify that the signal remains blocked
when the signal handler completes?

My implementation of queued signals in ksh93 needs to store each of the
siginfo_t
structs for signals that have trap handlers until the trap handlers are
executed. My implementation calls malloc() in the signal handler to get
memory to store the siginfo_t
structs, but posix does not require that malloc() be async safe.

While our malloc() implementation is asyc safe, the standard does not
require this and therefore it can't use a standard malloc.

If the signal could be blocked until the handler function is called, queued
signals could be implemented in a portable fashion.
Rich Felker
2014-10-14 00:02:45 UTC
Permalink
Post by David Korn
By default, when a signal handler is invoked, the signal is blocked and
then released when the signal handler completes.
Is there any way in the standard to specify that the signal remains blocked
when the signal handler completes?
While I see nothing in the standard which officially permits this
usage, the way I do this is by calling sigaddset on the uc_sigmask
member of the ucontext_t obtained as the third argument of the signal
handler with SA_SIGINFO. I find it very useful and would love to see
the standard officially endorse this usage as portable. I've only
tested it on Linux but I suspect it works on any system; kernel
implementors would have to go out of their way to break it (storing
the saved signal mask on the stack twice and giving you just a copy in
the ucontext).

Would there be support for adding a requirement along these lines?

Rich
Carlos O'Donell
2014-10-16 12:14:30 UTC
Permalink
Post by Rich Felker
Post by David Korn
By default, when a signal handler is invoked, the signal is blocked and
then released when the signal handler completes.
Is there any way in the standard to specify that the signal remains blocked
when the signal handler completes?
While I see nothing in the standard which officially permits this
usage, the way I do this is by calling sigaddset on the uc_sigmask
member of the ucontext_t obtained as the third argument of the signal
handler with SA_SIGINFO. I find it very useful and would love to see
the standard officially endorse this usage as portable. I've only
tested it on Linux but I suspect it works on any system; kernel
implementors would have to go out of their way to break it (storing
the saved signal mask on the stack twice and giving you just a copy in
the ucontext).
That's a very clever trick. I like it a lot. If I understand correctly
you need to do this because the language of the standard says the
original mask is restored as part of the return of the handler?
Post by Rich Felker
Would there be support for adding a requirement along these lines?
I would endorse it.

Cheers,
Carlos.
Rich Felker
2014-10-16 15:20:55 UTC
Permalink
Post by Carlos O'Donell
Post by Rich Felker
Post by David Korn
By default, when a signal handler is invoked, the signal is blocked and
then released when the signal handler completes.
Is there any way in the standard to specify that the signal remains blocked
when the signal handler completes?
While I see nothing in the standard which officially permits this
usage, the way I do this is by calling sigaddset on the uc_sigmask
member of the ucontext_t obtained as the third argument of the signal
handler with SA_SIGINFO. I find it very useful and would love to see
the standard officially endorse this usage as portable. I've only
tested it on Linux but I suspect it works on any system; kernel
implementors would have to go out of their way to break it (storing
the saved signal mask on the stack twice and giving you just a copy in
the ucontext).
That's a very clever trick. I like it a lot. If I understand correctly
you need to do this because the language of the standard says the
original mask is restored as part of the return of the handler?
Yes, normally the original mask is restored; the trick here is
changing the storage of the original mask so that a different mask is
restored.

FYI this is needed for one important corner case in the thread
cancellation design glibc is planning to adopt -- if the cancellation
signal arrives during a signal handler at a non cancellation point,
but the signal handler had interrupted a cancellation point, the only
way to make this work is to re-raise the signal but leave it blocked
when the cancellation signal handler returns, so that the
"at-cancellation-point" predicate is re-checked when the outer signal
handler returns. Of course this is all part of the implementation, so
whether POSIX adopts such a feature as standard for use by
applications is independent of glibc's (and currently, musl's) ability
to use it in implementing cancellation.
Post by Carlos O'Donell
Post by Rich Felker
Would there be support for adding a requirement along these lines?
I would endorse it.
Good to hear. Thanks!

Rich
Richard Hansen
2014-10-17 16:41:43 UTC
Permalink
Post by Rich Felker
Post by David Korn
By default, when a signal handler is invoked, the signal is blocked and
then released when the signal handler completes.
Is there any way in the standard to specify that the signal remains blocked
when the signal handler completes?
While I see nothing in the standard which officially permits this
usage, the way I do this is by calling sigaddset on the uc_sigmask
member of the ucontext_t obtained as the third argument of the signal
handler with SA_SIGINFO. I find it very useful and would love to see
the standard officially endorse this usage as portable. I've only
tested it on Linux but I suspect it works on any system; kernel
implementors would have to go out of their way to break it (storing
the saved signal mask on the stack twice and giving you just a copy in
the ucontext).
Would there be support for adding a requirement along these lines?
Seems sensible to me, although I'd be more comfortable if there was
confirmation that this worked on other systems.

Also, in case you missed it from the minutes:

"There is not anything in the standard that currently addresses
this, but the standards developer feel that if there was a proposal
to add such behavior it could be addressed in a future revision."

Feel like submitting a bug report?

Thanks,
Richard
Rich Felker
2014-10-18 17:02:35 UTC
Permalink
Post by Richard Hansen
Post by Rich Felker
Post by David Korn
By default, when a signal handler is invoked, the signal is blocked and
then released when the signal handler completes.
Is there any way in the standard to specify that the signal remains blocked
when the signal handler completes?
While I see nothing in the standard which officially permits this
usage, the way I do this is by calling sigaddset on the uc_sigmask
member of the ucontext_t obtained as the third argument of the signal
handler with SA_SIGINFO. I find it very useful and would love to see
the standard officially endorse this usage as portable. I've only
tested it on Linux but I suspect it works on any system; kernel
implementors would have to go out of their way to break it (storing
the saved signal mask on the stack twice and giving you just a copy in
the ucontext).
Would there be support for adding a requirement along these lines?
Seems sensible to me, although I'd be more comfortable if there was
confirmation that this worked on other systems.
"There is not anything in the standard that currently addresses
this, but the standards developer feel that if there was a proposal
to add such behavior it could be addressed in a future revision."
Feel like submitting a bug report?
Yeah, but perhaps we should discuss where it should go a bit first? My
thought it that the simplest solution would be to do it in the
documentation for SA_SIGINFO under sigaction. We could add text to the
effect that when SA_SIGINFO is used, if the signal handler returns,
the signal mask is set to the current value of the uc_sigmask member
of the pointed-to ucontext_t, which may differ from the signal mask
that was active at the time the signal handler was invoked, if the
application has modified it.

We could also add language that changes to other members of the
ucontext_t have unspecified behavior, noting that some implementations
allow changes to other members (e.g. an application advancing the
saved program counter after emulating an unsupported instruction via a
SIGILL handler).

Rich
David Korn
2014-10-19 01:32:35 UTC
Permalink
I attached a program that you can run to see if this feature already exists
on your system. The exit status is 0 if it works on your system. and
non-zero otherwise. It works on ubuntu linux.
Post by David Korn
Post by Richard Hansen
Post by Rich Felker
Post by David Korn
By default, when a signal handler is invoked, the signal is blocked
and
Post by Richard Hansen
Post by Rich Felker
Post by David Korn
then released when the signal handler completes.
Is there any way in the standard to specify that the signal remains
blocked
Post by Richard Hansen
Post by Rich Felker
Post by David Korn
when the signal handler completes?
While I see nothing in the standard which officially permits this
usage, the way I do this is by calling sigaddset on the uc_sigmask
member of the ucontext_t obtained as the third argument of the signal
handler with SA_SIGINFO. I find it very useful and would love to see
the standard officially endorse this usage as portable. I've only
tested it on Linux but I suspect it works on any system; kernel
implementors would have to go out of their way to break it (storing
the saved signal mask on the stack twice and giving you just a copy in
the ucontext).
Would there be support for adding a requirement along these lines?
Seems sensible to me, although I'd be more comfortable if there was
confirmation that this worked on other systems.
"There is not anything in the standard that currently addresses
this, but the standards developer feel that if there was a proposal
to add such behavior it could be addressed in a future revision."
Feel like submitting a bug report?
Yeah, but perhaps we should discuss where it should go a bit first? My
thought it that the simplest solution would be to do it in the
documentation for SA_SIGINFO under sigaction. We could add text to the
effect that when SA_SIGINFO is used, if the signal handler returns,
the signal mask is set to the current value of the uc_sigmask member
of the pointed-to ucontext_t, which may differ from the signal mask
that was active at the time the signal handler was invoked, if the
application has modified it.
We could also add language that changes to other members of the
ucontext_t have unspecified behavior, noting that some implementations
allow changes to other members (e.g. an application advancing the
saved program counter after emulating an unsupported instruction via a
SIGILL handler).
Rich
Loading...