[Patch] Signal mask handling
Pierre A. Humblet
pierre@phumblet.no-ip.org
Fri Mar 12 02:05:00 GMT 2004
At 08:43 PM 3/11/2004 -0500, you wrote:
>On Thu, Mar 11, 2004 at 07:36:41PM -0500, Pierre A. Humblet wrote:
>>There was a problem: pause() calls handle_sigsuspend(), which overwrites
>>the oldmask set by _cygtls::interrupt_setup. It's all fixed, and I have
>>renamed newmask to deltamask in cygtls.h. I can send you a fresh patch
>>(everything, against cvs) now, or wait until you apply yours.
>
>Go ahead and send the patch.
>
>Btw, I removed the setting of oldmask in _cygtls::fixup_after_fork after
>I searched for oldmask last night after seeing your patch.
OK, I had set oldmask again just for the fixup. I have just deleted
that line without retesting.
>>BTW I noticed that Posix and Cygwin diverge on sigpause.
>>
>>Posix:
>>int sigpause(int sig);
>>The sigpause() function removes sig from the calling process' signal
>>mask and suspends the calling process until a signal is received. The
>>sigpause() function restores the process' signal mask to its original
>>state before returning.
>>
>>Cygwin
>>sigpause (int signal_mask)
>>{
>> return handle_sigsuspend ((sigset_t) signal_mask);
>>}
>
>Sorry, but I don't see any divergence. A reading of the above might
>seem to indicate that sigpause should return on the receipt of any
>signal but I notice that on linux (and one other UNIX that I tested this
>on) sigpause only returns on the receipt of a signal that has a handler
>associated with it. This makes sigpause equivalent to sigsuspend,
>AFAICT.
What I find strange is that usually sig is an integer (1-32), not a mask.
Compare the two following lines are from the same Posix page
void (*sigset(int sig, void (*disp)(int)))(int); <= clearly an integer
int sigpause(int sig); <= a mask???
2004-02-11 Pierre Humblet <pierre.humblet@ieee.org>
* cygtls.h (_cygtls::newmask): Delete member.
(_cygtls::newmask): New member.
* gendef (_sigdelayed): Replace the call to
set_process_mask by a call to set_process_mask_delta.
* exceptions.cc (handle_sigsuspend): Do not filter tempmask.
Or SIG_NONMASKABLE in deltamask as a flag.
(_cygtls::interrupt_setup): Set deltamask only.
(set_process_mask_delta): New function.
(_cygtls::call_signal_handler): Replace the first call to
set_process_mask by a call to set_process_mask_delta.
-------------- next part --------------
Index: cygtls.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/cygtls.h,v
retrieving revision 1.19
diff -u -p -r1.19 cygtls.h
--- cygtls.h 9 Mar 2004 01:24:08 -0000 1.19
+++ cygtls.h 12 Mar 2004 01:48:21 -0000
@@ -96,7 +96,7 @@ struct _cygtls
int saved_errno;
int sa_flags;
sigset_t oldmask;
- sigset_t newmask;
+ sigset_t deltamask;
HANDLE event;
int *errno_addr;
unsigned initialized;
Index: gendef
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/gendef,v
retrieving revision 1.15
diff -u -p -r1.15 gendef
--- gendef 9 Mar 2004 01:24:08 -0000 1.15
+++ gendef 12 Mar 2004 01:48:22 -0000
@@ -190,15 +190,13 @@ _sigdelayed:
movl %fs:4,%ebx
incl $tls::incyg(%ebx)
pushl $tls::saved_errno(%ebx) # saved errno
-3: pushl $tls::oldmask(%ebx) # oldmask
+ call _set_process_mask_delta
+ pushl %eax # oldmask
pushl $tls::sig(%ebx) # signal argument
pushl \$_sigreturn
call _reset_signal_arrived\@0
pushl $tls::func(%ebx) # signal func
- pushl $tls::newmask(%ebx) # newmask - eaten by set_process_mask
-
- call _set_process_mask\@4
cmpl \$0,$tls::threadkill(%ebx)#pthread_kill signal?
jnz 4f #yes. Callee clears signal number
movl \$0,$tls::sig(%ebx) # zero the signal number as a
Index: exceptions.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/exceptions.cc,v
retrieving revision 1.210
diff -u -p -r1.210 exceptions.cc
--- exceptions.cc 9 Mar 2004 01:24:08 -0000 1.210
+++ exceptions.cc 12 Mar 2004 01:48:24 -0000
@@ -594,8 +594,7 @@ handle_sigsuspend (sigset_t tempmask)
{
sigset_t oldmask = myself->getsigmask (); // Remember for restoration
- // Let signals we're interested in through.
- set_signal_mask (tempmask &= ~SIG_NONMASKABLE, oldmask);
+ set_signal_mask (tempmask, oldmask);
sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask);
pthread_testcancel ();
@@ -605,8 +604,9 @@ handle_sigsuspend (sigset_t tempmask)
/* A signal dispatch function will have been added to our stack and will
be hit eventually. Set the old mask to be restored when the signal
- handler returns. */
+ handler returns and indicate its presence by modifying deltamask. */
+ _my_tls.deltamask |= SIG_NONMASKABLE;
_my_tls.oldmask = oldmask; // Will be restored by signal handler
return -1;
}
@@ -696,8 +696,7 @@ _cygtls::interrupt_setup (int sig, void
struct sigaction& siga)
{
push ((__stack_t) sigdelayed, false);
- oldmask = myself->getsigmask ();
- newmask = oldmask | siga.sa_mask | SIGTOMASK (sig);
+ deltamask = (siga.sa_mask | SIGTOMASK (sig)) & ~SIG_NONMASKABLE;
sa_flags = siga.sa_flags;
func = (void (*) (int)) handler;
saved_errno = -1; // Flag: no errno to save
@@ -926,6 +925,27 @@ sighold (int sig)
return 0;
}
+/* Update the signal mask for this process
+ and return the old mask.
+ Called from sigdelayed */
+extern "C" sigset_t
+set_process_mask_delta ()
+{
+ mask_sync->acquire (INFINITE);
+ sigset_t newmask, oldmask;
+
+ if (_my_tls.deltamask & SIG_NONMASKABLE)
+ oldmask = _my_tls.oldmask; /* from handle_sigsuspend */
+ else
+ oldmask = myself->getsigmask ();
+ newmask = (oldmask | _my_tls.deltamask) & ~SIG_NONMASKABLE;
+ sigproc_printf ("oldmask %p, newmask %p, deltamask %p", oldmask, newmask,
+ _my_tls.deltamask);
+ myself->setsigmask (newmask);
+ mask_sync->release ();
+ return oldmask;
+}
+
/* Set the signal mask for this process.
Note that some signals are unmaskable, as in UNIX. */
extern "C" void __stdcall
@@ -1178,9 +1198,8 @@ _cygtls::call_signal_handler ()
(void) pop ();
reset_signal_arrived ();
- sigset_t this_oldmask = oldmask;
+ sigset_t this_oldmask = set_process_mask_delta ();
int this_errno = saved_errno;
- set_process_mask (newmask);
incyg--;
sig = 0;
sigfunc (thissig);
More information about the Cygwin-patches
mailing list