Signal delivered while blocked

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Signal delivered while blocked

Noah Misch
The attached demonstration program blocks signals (with sigprocmask()) to
achieve mutual exclusion between signal handlers.  It aborts upon receipt of a
blocked signal.  On "CYGWIN_NT-10.0 2.7.0(0.306/5/3) 2017-02-12 13:18 x86_64",
signals regularly arrive despite being blocked.  Essential parts of the
program include handling two signal numbers and having handlers run for at
least 1-2ms; this problem goes away if I remove one of those attributes.
GNU/Linux, AIX, Solaris, and "CYGWIN_NT-6.0 1.7.27(0.271/5/3) 2013-12-09 11:57
i686" never deliver a blocked signal to this program.  I think this Cygwin
behavior is non-conforming.

PostgreSQL trouble prompted this report; the demonstration program is based on
the "postmaster" architecture.  postmaster SIGCHLD and SIGUSR1 handlers block
most signals, and they cannot cope with interrupts from blocked signals.

Thanks,
nm


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

sigprocmask-exclusion.c (3K) Download Attachment
cygcheck.out (44K) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Signal delivered while blocked

Corinna Vinschen-2
On Aug  4 00:44, Noah Misch wrote:
> The attached demonstration program blocks signals (with sigprocmask()) to
> achieve mutual exclusion between signal handlers.  It aborts upon receipt of a
> blocked signal.  On "CYGWIN_NT-10.0 2.7.0(0.306/5/3) 2017-02-12 13:18 x86_64",
> signals regularly arrive despite being blocked.  Essential parts of the
> program include handling two signal numbers and having handlers run for at
> least 1-2ms; this problem goes away if I remove one of those attributes.
> GNU/Linux, AIX, Solaris, and "CYGWIN_NT-6.0 1.7.27(0.271/5/3) 2013-12-09 11:57
> i686" never deliver a blocked signal to this program.  I think this Cygwin
> behavior is non-conforming.

Thanks for the testcase.  I debugged this a while today but the problem
is far from trivial, apparently.  Don't hold your breath for a quick
solution.


Corinna

--
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Signal delivered while blocked

Kaz Kylheku
On 04.08.2017 10:02, Corinna Vinschen wrote:

> On Aug  4 00:44, Noah Misch wrote:
>> The attached demonstration program blocks signals (with sigprocmask())
>> to
>> achieve mutual exclusion between signal handlers.  It aborts upon
>> receipt of a
>> blocked signal.  On "CYGWIN_NT-10.0 2.7.0(0.306/5/3) 2017-02-12 13:18
>> x86_64",
>> signals regularly arrive despite being blocked.  Essential parts of
>> the
>> program include handling two signal numbers and having handlers run
>> for at
>> least 1-2ms; this problem goes away if I remove one of those
>> attributes.
>> GNU/Linux, AIX, Solaris, and "CYGWIN_NT-6.0 1.7.27(0.271/5/3)
>> 2013-12-09 11:57
>> i686" never deliver a blocked signal to this program.  I think this
>> Cygwin
>> behavior is non-conforming.
>
> Thanks for the testcase.  I debugged this a while today but the problem
> is far from trivial, apparently.  Don't hold your breath for a quick
> solution.

Hi! It seems I haven't grasped at straws in a few weeks, so I'm
eager to tug on some dry turf. What the hay, you know?

The test case depends on accesses to the global variable sigblocked not
to be reordered w.r.t. siggprocmask calls.

It is important that the variable not be set to 1 until after the
signals are
blocked, and be reset to 0 until after they are unblocked.

Thus, the variable should be declared volatile.

(Even basic ISO C says that variables modified by signal handlers
shall be of type "volatile sig_atomic_t", not just "atomic_t").

Although I would be surprised if this were actually happening, in
principle
at least, compiler could be too clever and "just know" that the
sigprocmask
standard library function has no interactions with a user-defined global
variable and so the order of the call with respect to the manipulation
of that variable doesn't matter.

Also, related remarks: for the reason that we can't factor out compiler
behavior, with absolute certainty, it would be good to mention not only
the system versions but also GCC. The compiler differs, obviously,
between Cygwin 1.7 and 2.7; not to mention that the case is reported
against i686 of the one, and x86_74 of the other.

Cheers ...

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Signal delivered while blocked

Noah Misch
On Fri, Aug 04, 2017 at 11:58:51AM -0700, Kaz Kylheku wrote:

> On 04.08.2017 10:02, Corinna Vinschen wrote:
> >On Aug  4 00:44, Noah Misch wrote:
> >>The attached demonstration program blocks signals (with sigprocmask())
> >>to
> >>achieve mutual exclusion between signal handlers.  It aborts upon
> >>receipt of a
> >>blocked signal.  On "CYGWIN_NT-10.0 2.7.0(0.306/5/3) 2017-02-12 13:18
> >>x86_64",
> >>signals regularly arrive despite being blocked.  Essential parts of the
> >>program include handling two signal numbers and having handlers run for
> >>at
> >>least 1-2ms; this problem goes away if I remove one of those
> >>attributes.
> >>GNU/Linux, AIX, Solaris, and "CYGWIN_NT-6.0 1.7.27(0.271/5/3)
> >>2013-12-09 11:57
> >>i686" never deliver a blocked signal to this program.  I think this
> >>Cygwin
> >>behavior is non-conforming.
> >
> >Thanks for the testcase.  I debugged this a while today but the problem
> >is far from trivial, apparently.  Don't hold your breath for a quick
> >solution.

Understood.  Thanks for studying it.

> The test case depends on accesses to the global variable sigblocked not
> to be reordered w.r.t. siggprocmask calls.
>
> It is important that the variable not be set to 1 until after the signals
> are
> blocked, and be reset to 0 until after they are unblocked.
>
> Thus, the variable should be declared volatile.

Agreed, but ...

> Although I would be surprised if this were actually happening

... indeed, that didn't change the result.

> Also, related remarks: for the reason that we can't factor out compiler
> behavior, with absolute certainty, it would be good to mention not only
> the system versions but also GCC. The compiler differs, obviously,
> between Cygwin 1.7 and 2.7; not to mention that the case is reported
> against i686 of the one, and x86_74 of the other.

The Cygwin 2.7 system has gcc-core 5.4.0-1.  The unaffected Cygwin 1.7 system
has gcc-core 4.8.2-2.

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Signal delivered while blocked

Houder
In reply to this post by Noah Misch
On Fri, 4 Aug 2017 00:44:45, Noah Misch wrote:

> --UugvWAfsgieZRqgk
> Content-Type: text/plain; charset=us-ascii
> Content-Disposition: inline
>
> The attached demonstration program blocks signals (with sigprocmask()) to
> achieve mutual exclusion between signal handlers.  It aborts upon receipt of a
> blocked signal.  On "CYGWIN_NT-10.0 2.7.0(0.306/5/3) 2017-02-12 13:18 x86_64",
> signals regularly arrive despite being blocked.  Essential parts of the
> program include handling two signal numbers and having handlers run for at
> least 1-2ms; this problem goes away if I remove one of those attributes.
> GNU/Linux, AIX, Solaris, and "CYGWIN_NT-6.0 1.7.27(0.271/5/3) 2013-12-09 11:57
> i686" never deliver a blocked signal to this program.  I think this Cygwin
> behavior is non-conforming.

Hi Noah,

I do not think that Cygwin is the problem here; your code is the problem
here, I believe.

Please, study, for example, chapters 20 and 21 of LPI (Linux Programming
Interface by Michael Kerrisk).

(20.10 The Signal Mask (Blocking Signal Delivery)
(20.13 Changing Signal Dispositions: sigaction())

You cannot use sigprocmask() like you do; you cannot use SIG_SETMASK as
a parameter in sigprocmask() within the context of a handler.

Cygwin exhibits misbehaviour in case of your code, because it is slower
than Linux; however, the code is also wrong for Linux.

The misbehaviour occurs as result of nested interrupts in case of your
code (yes, nested interrupts are possible with Linux/Unix!).
However your code does not experience nesting under Linux, because, as
I said, Linux is faster than Cygwin.

-----
The simplest way to exclude one signal from another, is to specify the
signal (or signals) in the sa_mask of the sigaction parameter ...

    see sigaction()

-----
However if you desire 'control' during the execution of a handler, you
have to resort to sigprocmask(), and use SIG_BLOCK and SIG_UNBLOCK, in
order to add and remove a specific signal to/from the mask.

    see sigprocmask()

You cannot use SIG_SETMASK in that context.

Regards,

Henri

=====


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Signal delivered while blocked (2)

Houder
On 2017-08-14 08:03, Houder wrote:

> On Fri, 4 Aug 2017 00:44:45, Noah Misch wrote:
>> --UugvWAfsgieZRqgk
>> Content-Type: text/plain; charset=us-ascii
>> Content-Disposition: inline
>>
>> The attached demonstration program blocks signals (with sigprocmask())
>> to
>> achieve mutual exclusion between signal handlers.  It aborts upon
>> receipt of a
>> blocked signal.  On "CYGWIN_NT-10.0 2.7.0(0.306/5/3) 2017-02-12 13:18
>> x86_64",
>> signals regularly arrive despite being blocked.  Essential parts of
>> the
>> program include handling two signal numbers and having handlers run
>> for at
>> least 1-2ms; this problem goes away if I remove one of those
>> attributes.
>> GNU/Linux, AIX, Solaris, and "CYGWIN_NT-6.0 1.7.27(0.271/5/3)
>> 2013-12-09 11:57
>> i686" never deliver a blocked signal to this program.  I think this
>> Cygwin
>> behavior is non-conforming.
>
> Hi Noah,
>
> I do not think that Cygwin is the problem here; your code is the
> problem
> here, I believe.
[snip]

> You cannot use SIG_SETMASK in that context.

You cannot use SIG_SETMASK in that context in the way you do.

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Signal delivered while blocked

Noah Misch
In reply to this post by Houder
On Mon, Aug 14, 2017 at 08:03:07AM +0200, Houder wrote:

> On Fri, 4 Aug 2017 00:44:45, Noah Misch wrote:
> > The attached demonstration program blocks signals (with sigprocmask()) to
> > achieve mutual exclusion between signal handlers.  It aborts upon receipt of a
> > blocked signal.  On "CYGWIN_NT-10.0 2.7.0(0.306/5/3) 2017-02-12 13:18 x86_64",
> > signals regularly arrive despite being blocked.  Essential parts of the
> > program include handling two signal numbers and having handlers run for at
> > least 1-2ms; this problem goes away if I remove one of those attributes.
> > GNU/Linux, AIX, Solaris, and "CYGWIN_NT-6.0 1.7.27(0.271/5/3) 2013-12-09 11:57
> > i686" never deliver a blocked signal to this program.  I think this Cygwin
> > behavior is non-conforming.

> I do not think that Cygwin is the problem here; your code is the problem
> here, I believe.
>
> Please, study, for example, chapters 20 and 21 of LPI (Linux Programming
> Interface by Michael Kerrisk).
>
> (20.10 The Signal Mask (Blocking Signal Delivery)
> (20.13 Changing Signal Dispositions: sigaction())
>
> You cannot use sigprocmask() like you do; you cannot use SIG_SETMASK as
> a parameter in sigprocmask() within the context of a handler.

What words in those chapters prompted your conclusion?  I see nothing in 20.10
or 20.13 about contextual restrictions on SIG_SETMASK.  Posix mentions no such
restrictions in its sigprocmask() page, and Posix does say:

  The following table defines a set of functions that shall be
  async-signal-safe. Therefore, applications can call them, without restriction,
  from signal-catching functions.
  ...
  sigprocmask()
  -- http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html

> Cygwin exhibits misbehaviour in case of your code, because it is slower
> than Linux; however, the code is also wrong for Linux.
>
> The misbehaviour occurs as result of nested interrupts in case of your
> code (yes, nested interrupts are possible with Linux/Unix!).
> However your code does not experience nesting under Linux, because, as
> I said, Linux is faster than Cygwin.

My code *does* experience signal handler nesting on Linux.  In fact, handlers
nest far more quickly than they do under Cygwin.  However, all its nesting
under Linux takes place outside the sigprocmask()-bounded critical section.
The algorithm that inspired this test case tolerates that nesting, but it does
not tolerate nesting within the critical section.

> The simplest way to exclude one signal from another, is to specify the
> signal (or signals) in the sa_mask of the sigaction parameter ...

That is true.  However, as you discovered in your other thread, it is not an
effective workaround for $SUBJECT.

nm

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Signal delivered while blocked

Houder
On 2017-08-19 10:01, Noah Misch wrote:
> What words in those chapters prompted your conclusion?  I see nothing
> in 20.10
> or 20.13 about contextual restrictions on SIG_SETMASK.  Posix mentions
> no such
> restrictions in its sigprocmask() page, and Posix does say:

Noah,

My apologies! My command over the English language is poor. English is
not
my native tongue, and I have hard time getting my point across in
English.

I am not a language genius.

Let me try again with regard to the most important thing.

Keep in mind, that I replied to your post after I had executed your code
on
Linux (and had a hard look at your code).

I was astonished to see the 'run-away' stack on Linux ...

("that cannot be correct", was my thinking)

I should have written in my previous reply:

     "you cannot make use of SIG_SETMASK in sigprocmask() within the
context
      of a handler", IN THE WAY YOU DO IT"
or
     "in the body of a signal handler, one cannot modify the signal mask
w/o
      knowing what it was at the beginning"

  1. when a signal handler is entered, the kernel will (usually) have
added
     the signal number, associated to the handler, to the mask
  2. the execution of a handler may be nested within the execution of
another

Consequently, one does not know what the signal mask is at the beginning
of
the critical section in the handler.

That is why you want to save the current signal mask when modifying it
(at
the start of the critical section).

At the end of the critical section, one should restore the old signal
mask,
or test it in case one want to revert the signal mask "by hand".

Take a look at listing 20-5 in LPI.

And yes, the above should be present in a text book about U/Linux (and
yes,
it is not explicitly stated in LPI).

Regards,

Henri

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Signal delivered while blocked

Noah Misch
On Sun, Aug 20, 2017 at 02:18:45PM +0200, Houder wrote:
> On 2017-08-19 10:01, Noah Misch wrote:
> >What words in those chapters prompted your conclusion?  I see nothing in
> >20.10 or 20.13 about contextual restrictions on SIG_SETMASK.  Posix
> >mentions no such restrictions in its sigprocmask() page, and Posix does
> >say:

> Keep in mind, that I replied to your post after I had executed your code on
> Linux (and had a hard look at your code).
>
> I was astonished to see the 'run-away' stack on Linux ...
>
> ("that cannot be correct", was my thinking)
>
> I should have written in my previous reply:
>
>     "you cannot make use of SIG_SETMASK in sigprocmask() within the context
>      of a handler", IN THE WAY YOU DO IT"
> or
>     "in the body of a signal handler, one cannot modify the signal mask w/o
>      knowing what it was at the beginning"
>
>  1. when a signal handler is entered, the kernel will (usually) have added
>     the signal number, associated to the handler, to the mask
>  2. the execution of a handler may be nested within the execution of another
>
> Consequently, one does not know what the signal mask is at the beginning of
> the critical section in the handler.
>
> That is why you want to save the current signal mask when modifying it (at
> the start of the critical section).
>
> At the end of the critical section, one should restore the old signal mask,
> or test it in case one want to revert the signal mask "by hand".
>
> Take a look at listing 20-5 in LPI.

If the test program has undefined behavior according to Posix, I want to know
that.  If the test program can cause $SUBJECT according to Posix, I want to
know that.

Following your advice above would not remove undefined behavior or prevent
$SUBJECT.  It would make the signal-using software more maintainable and
reduce the risk of consuming all stack space.  Those are good goals for
authors to pursue, but this thread is about delivery of blocked signals.

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Loading...