@@ -106,12 +106,16 @@ class pending_signals
106106{
107107 sigpacket sigs[_NSIG + 1 ];
108108 sigpacket start;
109+ SRWLOCK queue_lock;
109110 bool retry;
111+ void lock () { AcquireSRWLockExclusive (&queue_lock); }
112+ void unlock () { ReleaseSRWLockExclusive (&queue_lock); }
110113
111114public:
115+ pending_signals (): queue_lock (SRWLOCK_INIT) {}
112116 void add (sigpacket&);
113117 bool pending () {retry = !!start.next ; return retry;}
114- void clear (int sig);
118+ void clear (int sig, bool need_lock );
115119 void clear (_cygtls *tls);
116120 friend void sig_dispatch_pending (bool );
117121 friend void wait_sig (VOID *arg);
@@ -427,23 +431,27 @@ proc_terminate ()
427431
428432/* Clear pending signal */
429433void
430- sig_clear (int sig)
434+ sig_clear (int sig, bool need_lock )
431435{
432- sigq.clear (sig);
436+ sigq.clear (sig, need_lock );
433437}
434438
435439/* Clear pending signals of specific si_signo.
436440 Called from sigpacket::process(). */
437441void
438- pending_signals::clear (int sig)
442+ pending_signals::clear (int sig, bool need_lock )
439443{
440444 sigpacket *q = sigs + sig;
441445 if (!sig || !q->si .si_signo )
442446 return ;
447+ if (need_lock)
448+ lock ();
443449 q->si .si_signo = 0 ;
444450 q->prev ->next = q->next ;
445451 if (q->next )
446452 q->next ->prev = q->prev ;
453+ if (need_lock)
454+ unlock ();
447455}
448456
449457/* Clear pending signals of specific thread. Called under TLS lock from
@@ -453,6 +461,7 @@ pending_signals::clear (_cygtls *tls)
453461{
454462 sigpacket *q = &start;
455463
464+ lock ();
456465 while ((q = q->next ))
457466 if (q->sigtls == tls)
458467 {
@@ -461,6 +470,7 @@ pending_signals::clear (_cygtls *tls)
461470 if (q->next )
462471 q->next ->prev = q->prev ;
463472 }
473+ unlock ();
464474}
465475
466476/* Clear pending signals of specific thread. Called from _cygtls::remove */
@@ -1313,11 +1323,13 @@ pending_signals::add (sigpacket& pack)
13131323 if (se->si .si_signo )
13141324 return ;
13151325 *se = pack;
1326+ lock ();
13161327 se->next = start.next ;
13171328 se->prev = &start;
13181329 se->prev ->next = se;
13191330 if (se->next )
13201331 se->next ->prev = se;
1332+ unlock ();
13211333}
13221334
13231335/* Process signals by waiting for signal data to arrive in a pipe.
@@ -1398,6 +1410,7 @@ wait_sig (VOID *)
13981410 bool issig_wait;
13991411
14001412 *pack.mask = 0 ;
1413+ sigq.lock ();
14011414 while ((q = q->next ))
14021415 {
14031416 _cygtls *sigtls = q->sigtls ?: _main_tls;
@@ -1411,6 +1424,7 @@ wait_sig (VOID *)
14111424 }
14121425 }
14131426 }
1427+ sigq.unlock ();
14141428 }
14151429 break ;
14161430 case __SIGPENDING:
@@ -1419,6 +1433,7 @@ wait_sig (VOID *)
14191433
14201434 *pack.mask = 0 ;
14211435 tl_entry = cygheap->find_tls (pack.sigtls );
1436+ sigq.lock ();
14221437 while ((q = q->next ))
14231438 {
14241439 /* Skip thread-specific signals for other threads. */
@@ -1427,6 +1442,7 @@ wait_sig (VOID *)
14271442 if (pack.sigtls ->sigmask & (bit = SIGTOMASK (q->si .si_signo )))
14281443 *pack.mask |= bit;
14291444 }
1445+ sigq.unlock ();
14301446 cygheap->unlock_tls (tl_entry);
14311447 }
14321448 break ;
@@ -1461,7 +1477,7 @@ wait_sig (VOID *)
14611477 break ;
14621478 default : /* Normal (positive) signal */
14631479 if (pack.si .si_signo < 0 )
1464- sig_clear (-pack.si .si_signo );
1480+ sig_clear (-pack.si .si_signo , true );
14651481 else
14661482 sigq.add (pack);
14671483 fallthrough;
@@ -1474,6 +1490,7 @@ wait_sig (VOID *)
14741490 {
14751491 /* Check the queue for signals. There will always be at least one
14761492 thing on the queue if this was a valid signal. */
1493+ sigq.lock ();
14771494 while ((q = q->next ))
14781495 {
14791496 if (q->si .si_signo && q->process () > 0 )
@@ -1484,6 +1501,7 @@ wait_sig (VOID *)
14841501 q->next ->prev = q->prev ;
14851502 }
14861503 }
1504+ sigq.unlock ();
14871505 /* At least one signal still queued? The event is used in select
14881506 only, and only to decide if WFMO should wake up in case a
14891507 signalfd is waiting via select/poll for being ready to read a
0 commit comments