* DevNotes: Add entry cgf-000013.

* cygserver_ipc.h (ipc_set_proc_info): Use _cygtls::ipc_set_proc_info to set
per-thread signal arrived value.
* cygthread.cc (cygthread::detach): Use per-thread signal_arrived via
set_thread_waiting.
* fork.cc (_cygtls::fixup_after_fork): Clear signal_arrived.
(_cygtls::remove): Close any signal_arrived handle when thread exists.
(_cygtls::find_tls): Remove unneeded function.
* cygtls.h: Update copyright.
(class _cygtls): Reorganize to help avoid rebuilding newlib when structure
changes.
(_cygtls::event): Delete.
(_cygtls::threadkill): Ditto.
(_cygtls::signal_waiting): Declare new bool.
(_cygtls::find_tls): Delete declaration.
(_cygtls::set_threadkill): Ditto.
(_cygtls::reset_threadkill): Ditto.
(_cygtls::set_signal_arrived): Declare new function.
(class set_thread_waiting): Declare new class.
* cygwait.cc (cw_nowait_storage): Define.
(cygwait): Set per-thread signal_arrived via set_thread_waiting.  Don't
special-case _main_tls.
* cygwait.h (cw_nowait): Define.
(cw_infinite): Ditto.
(cygwait): Redefine pathological wait-only case.
* dcrt0.cc (dll_crt0_0): Remove call to now-defunct events_init().
(dll_crt0_1): Remove call to now-defunct create_signal_arrived().
* exceptions.cc: Reflect set_signal_mask() argument reordering throughout.
Remove signal mask synchronization throughout.
(events_init): Delete definition.
(mask_sync): Delete now-unneeded mask synchronization.
(set_signal_mask): Reverse order of arguments to "standard" to, from layout.
Rename "newmask" argument to "setmask".  Remove debugging.
(sig_handle_tty_stop): Use cancelable_wait rather than WFMO.
(_cygtls::interrupt_setup): Don't treat "threadkill" events specially.
Conditionally set signal_arrived depending on whether the thread has created it
or not.
(sigpacket::process): Reorganize to reflect thread-specific sending of signals
which is more in line with the way it was actually supposed to work.
* fhandler_socket.cc (get_inet_addr): Use cancelable_wait rather than
IsEventSignalled to avoid potential race.
(fhandler_socket::wait_for_events): Set signal_arrived event using
set_thread_waiting().
(fhandler_socket::close): Use cygwait for the case of just waiting 10 ms for a
signal.
* fhandler_tape.cc (fhandler_dev_tape::_lock): Use cancelable_wait rather than
WFMO.  Redo switch/case tests accordingly.
* fhandler_termios.cc (fhandler_termios::bg_check): Use cygwait for case of
just waiting 0 ms for a potential signal.
* fhandler_tty.cc (fhandler_pty_master::process_slave_output): Use
cancelable_wait rather than WFSO.
* fhandler_windows.cc (fhandler_windows::read): Set per-thread signal_arrived
via set_thread_waiting().
* flock.cc (lf_setlock): Ditto.
* select.cc (pselect): Ditto.  Set per-thread signal_arrived using
set_thread_waiting().
* gendef: Don't special case handling of _cygtls::sig for threads.
* gentls_offsets: Use #pragma once in tlsoffsets.h.
* ntdll.h: Use #pragma once.
* poll.cc: Reflect set_signal_mask() argument reordering.
* posix_ipc.cc (ipc_mutex_lock): Use cancelable_wait rather than WFMO.
(ipc_cond_timedwait): Set perl-thread signal arrived using
set_thread_waiting().
* security.h: Use #pragma once.
* signal.cc (abort): Reflect set_signal_mask() argument reordering.
(clock_nanosleep): Ditto.  Change call to cancelable_wait to properly specify
handling of cancel and interrupt.
(sigwaitinfo): Remove handling of per-thread event in favor of per-thread
signal_arrived.  Use cancelable_wait rather than WFSO.
* sigproc.cc (signal_arrived): Delete definition.
(create_signal_arrived): Ditto.
* sigproc.h (signal_arrived): Delete declaration.
(set_signal_mask): Avoid defining as a "C" function.  Don't conditionally
declare.
(create_signal_arrived): Delete declaration.
* syscalls.cc (rename): Use cygwait() rather than WFSO.
* thread.h (fast_mutex::lock): Use cw_infinite rather than LARGE_NULL.
* wait.cc (wait4): Ditto.
* thread.cc (pthread_mutex::lock): Ditto.
(pthread::join): Ditto.
(semaphore::_wait): Ditto.
(pthread_kill): Remove set_threadkill() accommodation.
* tlsoffsets.h: Regenerate.
This commit is contained in:
Christopher Faylor 2012-07-21 22:58:20 +00:00
parent b8a84b73d7
commit 962f9a2ccc
31 changed files with 389 additions and 388 deletions

View File

@ -1,3 +1,90 @@
2012-07-21 Christopher Faylor <me.cygwin2012@cgf.cx>
* DevNotes: Add entry cgf-000013.
* cygserver_ipc.h (ipc_set_proc_info): Use _cygtls::ipc_set_proc_info
to set per-thread signal arrived value.
* cygthread.cc (cygthread::detach): Use per-thread signal_arrived via
set_thread_waiting.
* fork.cc (_cygtls::fixup_after_fork): Clear signal_arrived.
(_cygtls::remove): Close any signal_arrived handle when thread exists.
(_cygtls::find_tls): Remove unneeded function.
* cygtls.h: Update copyright.
(class _cygtls): Reorganize to help avoid rebuilding newlib when
structure changes.
(_cygtls::event): Delete.
(_cygtls::threadkill): Ditto.
(_cygtls::signal_waiting): Declare new bool.
(_cygtls::find_tls): Delete declaration.
(_cygtls::set_threadkill): Ditto.
(_cygtls::reset_threadkill): Ditto.
(_cygtls::set_signal_arrived): Declare new function.
(class set_thread_waiting): Declare new class.
* cygwait.cc (cw_nowait_storage): Define.
(cygwait): Set per-thread signal_arrived via set_thread_waiting. Don't
special-case _main_tls.
* cygwait.h (cw_nowait): Define.
(cw_infinite): Ditto.
(cygwait): Redefine pathological wait-only case.
* dcrt0.cc (dll_crt0_0): Remove call to now-defunct events_init().
(dll_crt0_1): Remove call to now-defunct create_signal_arrived().
* exceptions.cc: Reflect set_signal_mask() argument reordering
throughout. Remove signal mask synchronization throughout.
(events_init): Delete definition.
(mask_sync): Delete now-unneeded mask synchronization.
(set_signal_mask): Reverse order of arguments to "standard" to, from
layout. Rename "newmask" argument to "setmask". Remove debugging.
(sig_handle_tty_stop): Use cancelable_wait rather than WFMO.
(_cygtls::interrupt_setup): Don't treat "threadkill" events specially.
Conditionally set signal_arrived depending on whether the thread has
created it or not.
(sigpacket::process): Reorganize to reflect thread-specific sending of
signals which is more in line with the way it was actually supposed to
work.
* fhandler_socket.cc (get_inet_addr): Use cancelable_wait rather than
IsEventSignalled to avoid potential race.
(fhandler_socket::wait_for_events): Set signal_arrived event using
set_thread_waiting().
(fhandler_socket::close): Use cygwait for the case of just
waiting 10 ms for a signal.
* fhandler_tape.cc (fhandler_dev_tape::_lock): Use cancelable_wait
rather than WFMO. Redo switch/case tests accordingly.
* fhandler_termios.cc (fhandler_termios::bg_check): Use cygwait for
case of just waiting 0 ms for a potential signal.
* fhandler_tty.cc (fhandler_pty_master::process_slave_output): Use
cancelable_wait rather than WFSO.
* fhandler_windows.cc (fhandler_windows::read): Set per-thread
signal_arrived via set_thread_waiting().
* flock.cc (lf_setlock): Ditto.
* select.cc (pselect): Ditto. Set per-thread signal_arrived using
set_thread_waiting().
* gendef: Don't special case handling of _cygtls::sig for threads.
* gentls_offsets: Use #pragma once in tlsoffsets.h.
* ntdll.h: Use #pragma once.
* poll.cc: Reflect set_signal_mask() argument reordering.
* posix_ipc.cc (ipc_mutex_lock): Use cancelable_wait rather than WFMO.
(ipc_cond_timedwait): Set perl-thread signal arrived using
set_thread_waiting().
* security.h: Use #pragma once.
* signal.cc (abort): Reflect set_signal_mask() argument reordering.
(clock_nanosleep): Ditto. Change call to cancelable_wait to properly
specify handling of cancel and interrupt.
(sigwaitinfo): Remove handling of per-thread event in favor of
per-thread signal_arrived. Use cancelable_wait rather than WFSO.
* sigproc.cc (signal_arrived): Delete definition.
(create_signal_arrived): Ditto.
* sigproc.h (signal_arrived): Delete declaration.
(set_signal_mask): Avoid defining as a "C" function. Don't
conditionally declare.
(create_signal_arrived): Delete declaration.
* syscalls.cc (rename): Use cygwait() rather than WFSO.
* thread.h (fast_mutex::lock): Use cw_infinite rather than LARGE_NULL.
* wait.cc (wait4): Ditto.
* thread.cc (pthread_mutex::lock): Ditto.
(pthread::join): Ditto.
(semaphore::_wait): Ditto.
(pthread_kill): Remove set_threadkill() accommodation.
* tlsoffsets.h: Regenerate.
2012-07-21 Christopher Faylor <me.cygwin2012@cgf.cx> 2012-07-21 Christopher Faylor <me.cygwin2012@cgf.cx>
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MINOR): Bump to 17. * include/cygwin/version.h (CYGWIN_VERSION_DLL_MINOR): Bump to 17.

View File

@ -1,3 +1,24 @@
2012-07-21 cgf-000013
These changes reflect a revamp of the "wait for signal" functionality
which has existed in Cygwin through several signal massages.
We now create a signal event only when a thread is waiting for a signal
and arm it only for that thread. The "set_thread_waiting" function is
used to establish the event and set it in a location referencable by
the caller.
I still do not handle all of the race conditions. What happens when
a signal comes in just after a WF?O succeeds for some other purpose? I
suspect that it will arm the next WF?O call and the subsequent call to
call_signal_handler could cause a function to get an EINTR when possibly
it shouldn't have.
I haven't yet checked all of the test cases for the URL listed in the
previous entry.
Baby steps.
2012-06-12 cgf-000012 2012-06-12 cgf-000012
These changes are the preliminary for redoing the way threads wait for These changes are the preliminary for redoing the way threads wait for

View File

@ -43,7 +43,7 @@ ipc_set_proc_info (proc &blk)
blk.gidcnt = 0; blk.gidcnt = 0;
blk.gidlist = NULL; blk.gidlist = NULL;
blk.is_admin = false; blk.is_admin = false;
blk.signal_arrived = signal_arrived; _my_tls.set_signal_arrived (true, blk.signal_arrived);
} }
#endif /* __INSIDE_CYGWIN__ */ #endif /* __INSIDE_CYGWIN__ */

View File

@ -377,7 +377,7 @@ cygthread::detach (HANDLE sigwait)
unsigned n = 2; unsigned n = 2;
DWORD howlong = INFINITE; DWORD howlong = INFINITE;
w4[0] = sigwait; w4[0] = sigwait;
w4[1] = signal_arrived; set_thread_waiting here (w4[1]);
/* For a description of the below loop see the end of this file */ /* For a description of the below loop see the end of this file */
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
switch (res = WaitForMultipleObjects (n, w4, FALSE, howlong)) switch (res = WaitForMultipleObjects (n, w4, FALSE, howlong))

View File

@ -190,6 +190,7 @@ _cygtls::fixup_after_fork ()
sig = 0; sig = 0;
} }
stacklock = spinning = 0; stacklock = spinning = 0;
signal_arrived = NULL;
locals.select.sockevt = NULL; locals.select.sockevt = NULL;
locals.cw_timer = NULL; locals.cw_timer = NULL;
wq.thread_ev = NULL; wq.thread_ev = NULL;
@ -214,6 +215,13 @@ _cygtls::remove (DWORD wait)
/* FIXME: Need some sort of atthreadexit function to allow things like /* FIXME: Need some sort of atthreadexit function to allow things like
select to control this themselves. */ select to control this themselves. */
if (signal_arrived)
{
HANDLE h = signal_arrived;
signal_arrived = NULL;
CloseHandle (h);
}
/* Close handle and free memory used by select. */ /* Close handle and free memory used by select. */
if (locals.select.sockevt) if (locals.select.sockevt)
{ {
@ -254,31 +262,6 @@ _cygtls::push (__stack_t addr)
*stackptr++ = (__stack_t) addr; *stackptr++ = (__stack_t) addr;
} }
_cygtls *
_cygtls::find_tls (int sig)
{
static int NO_COPY threadlist_ix;
debug_printf ("signal %d\n", sig);
sentry here (INFINITE);
_cygtls *res = NULL;
threadlist_ix = -1;
myfault efault;
if (efault.faulted ())
cygheap->threadlist[threadlist_ix]->remove (INFINITE);
while (++threadlist_ix < (int) nthreads)
if (sigismember (&(cygheap->threadlist[threadlist_ix]->sigwait_mask), sig))
{
res = cygheap->threadlist[threadlist_ix];
break;
}
return res;
}
void void
_cygtls::set_siginfo (sigpacket *pack) _cygtls::set_siginfo (sigpacket *pack)
{ {

View File

@ -1,13 +1,12 @@
/* cygtls.h /* cygtls.h
Copyright 2003, 2004, 2005, 2008, 2009, 2010, 2011 Red Hat, Inc. Copyright 2003, 2004, 2005, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc.
This software is a copyrighted work licensed under the terms of the This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */ details. */
#ifndef _CYGTLS_H #pragma once
#define _CYGTLS_H
#include <signal.h> #include <signal.h>
#include <pwd.h> #include <pwd.h>
@ -158,6 +157,7 @@ typedef struct struct_waitq
/*gentls_offsets*/ /*gentls_offsets*/
#include "cygerrno.h" #include "cygerrno.h"
#include "security.h"
extern "C" int __sjfault (jmp_buf); extern "C" int __sjfault (jmp_buf);
extern "C" int __ljfault (jmp_buf, int); extern "C" int __ljfault (jmp_buf, int);
@ -169,27 +169,29 @@ typedef __uint32_t __stack_t;
class _cygtls class _cygtls
{ {
public: public:
void (*func) /*gentls_offsets*/(int)/*gentls_offsets*/; /* Please keep these two declarations first */
int saved_errno; struct _local_storage locals;
int sa_flags;
sigset_t oldmask;
sigset_t deltamask;
HANDLE event;
int *errno_addr;
sigset_t sigmask;
sigset_t sigwait_mask;
siginfo_t *sigwait_info;
struct ucontext thread_context;
DWORD thread_id;
unsigned threadkill;
siginfo_t infodata;
struct pthread *tid;
union union
{ {
struct _reent local_clib; struct _reent local_clib;
char __dontuse[8 * ((sizeof(struct _reent) + 4) / 8)]; char __dontuse[8 * ((sizeof(struct _reent) + 4) / 8)];
}; };
struct _local_storage locals; /**/
void (*func) /*gentls_offsets*/(int)/*gentls_offsets*/;
int saved_errno;
int sa_flags;
sigset_t oldmask;
sigset_t deltamask;
int *errno_addr;
sigset_t sigmask;
sigset_t sigwait_mask;
siginfo_t *sigwait_info;
HANDLE signal_arrived;
bool signal_waiting;
struct ucontext thread_context;
DWORD thread_id;
siginfo_t infodata;
struct pthread *tid;
class cygthread *_ctinfo; class cygthread *_ctinfo;
class san *andreas; class san *andreas;
waitq wq; waitq wq;
@ -205,7 +207,6 @@ public:
static void init (); static void init ();
void init_thread (void *, DWORD (*) (void *, void *)); void init_thread (void *, DWORD (*) (void *, void *));
static void call (DWORD (*) (void *, void *), void *); static void call (DWORD (*) (void *, void *), void *);
static struct _cygtls *find_tls (int sig);
void remove (DWORD); void remove (DWORD);
void push (__stack_t) __attribute__ ((regparm (2))); void push (__stack_t) __attribute__ ((regparm (2)));
__stack_t pop () __attribute__ ((regparm (1))); __stack_t pop () __attribute__ ((regparm (1)));
@ -229,14 +230,24 @@ public:
operator HANDLE () const {return tid->win32_obj_id;} operator HANDLE () const {return tid->win32_obj_id;}
#endif #endif
void set_siginfo (struct sigpacket *) __attribute__ ((regparm (3))); void set_siginfo (struct sigpacket *) __attribute__ ((regparm (3)));
void set_threadkill () {threadkill = true;}
void reset_threadkill () {threadkill = false;}
int call_signal_handler () __attribute__ ((regparm (1))); int call_signal_handler () __attribute__ ((regparm (1)));
void remove_wq (DWORD) __attribute__ ((regparm (1))); void remove_wq (DWORD) __attribute__ ((regparm (1)));
void fixup_after_fork () __attribute__ ((regparm (1))); void fixup_after_fork () __attribute__ ((regparm (1)));
void lock () __attribute__ ((regparm (1))); void lock () __attribute__ ((regparm (1)));
void unlock () __attribute__ ((regparm (1))); void unlock () __attribute__ ((regparm (1)));
bool locked () __attribute__ ((regparm (1))); bool locked () __attribute__ ((regparm (1)));
void set_signal_arrived (bool setit, HANDLE& h)
{
if (!setit)
signal_waiting = false;
else
{
if (!signal_arrived)
signal_arrived = CreateEvent (&sec_none_nih, false, false, NULL);
h = signal_arrived;
signal_waiting = true;
}
}
private: private:
void call2 (DWORD (*) (void *, void *), void *, void *) __attribute__ ((regparm (3))); void call2 (DWORD (*) (void *, void *), void *, void *) __attribute__ ((regparm (3)));
/*gentls_offsets*/ /*gentls_offsets*/
@ -304,6 +315,15 @@ public:
} }
}; };
#define __getreent() (&_my_tls.local_clib) class set_thread_waiting
{
public:
set_thread_waiting (bool setit, HANDLE& h) { _my_tls.set_signal_arrived (setit, h); }
set_thread_waiting (HANDLE& h) { _my_tls.set_signal_arrived (true, h); }
#endif /*_CYGTLS_H*/ /*gentls_offsets*/ operator int () const {return _my_tls.signal_waiting;}
~set_thread_waiting () { _my_tls.signal_waiting = false; }
};
#define __getreent() (&_my_tls.local_clib)
/*gentls_offsets*/

View File

@ -21,6 +21,8 @@
#define is_cw_sig_handle (mask & (is_cw_sig | is_cw_sig_eintr)) #define is_cw_sig_handle (mask & (is_cw_sig | is_cw_sig_eintr))
LARGE_INTEGER cw_nowait_storage;
DWORD DWORD
cancelable_wait (HANDLE object, PLARGE_INTEGER timeout, unsigned mask) cancelable_wait (HANDLE object, PLARGE_INTEGER timeout, unsigned mask)
{ {
@ -36,14 +38,13 @@ cancelable_wait (HANDLE object, PLARGE_INTEGER timeout, unsigned mask)
if (object) if (object)
wait_objects[num++] = object; wait_objects[num++] = object;
set_thread_waiting thread_waiting (is_cw_sig_handle, wait_objects[num]);
debug_printf ("thread waiting %d, signal_arrived %p", (int) thread_waiting, _my_tls.signal_arrived);
DWORD sig_n; DWORD sig_n;
if (!is_cw_sig_handle) if (!thread_waiting)
sig_n = WAIT_TIMEOUT + 1; sig_n = WAIT_TIMEOUT + 1;
else else
{ sig_n = WAIT_OBJECT_0 + num++;
sig_n = WAIT_OBJECT_0 + num++;
wait_objects[sig_n] = signal_arrived;
}
DWORD cancel_n; DWORD cancel_n;
if (!is_cw_cancel || !pthread::is_good_object (&thread) || if (!is_cw_cancel || !pthread::is_good_object (&thread) ||
@ -79,7 +80,7 @@ cancelable_wait (HANDLE object, PLARGE_INTEGER timeout, unsigned mask)
/* all set */; /* all set */;
else if (is_cw_sig_eintr) else if (is_cw_sig_eintr)
res = WAIT_SIGNALED; /* caller will deal with signals */ res = WAIT_SIGNALED; /* caller will deal with signals */
else if (_my_tls.call_signal_handler () || &_my_tls != _main_tls) else if (_my_tls.call_signal_handler ())
continue; continue;
break; break;
} }

View File

@ -22,7 +22,10 @@ enum cw_wait_mask
cw_sig_eintr = 0x0008 cw_sig_eintr = 0x0008
}; };
#define LARGE_NULL ((PLARGE_INTEGER) NULL) extern LARGE_INTEGER cw_nowait_storage;
#define cw_nowait (&cw_nowait_storage)
#define cw_infinite ((PLARGE_INTEGER) NULL)
const unsigned cw_std_mask = cw_cancel | cw_cancel_self | cw_sig; const unsigned cw_std_mask = cw_cancel | cw_cancel_self | cw_sig;
DWORD cancelable_wait (HANDLE, PLARGE_INTEGER timeout = NULL, DWORD cancelable_wait (HANDLE, PLARGE_INTEGER timeout = NULL,
@ -53,5 +56,5 @@ cygwait (HANDLE h, DWORD howlong = INFINITE)
static inline DWORD __attribute__ ((always_inline)) static inline DWORD __attribute__ ((always_inline))
cygwait (DWORD howlong) cygwait (DWORD howlong)
{ {
return cancelable_wait (NULL, howlong, cw_cancel | cw_sig_eintr); return cygwait (NULL, howlong);
} }

View File

@ -774,9 +774,6 @@ dll_crt0_0 ()
user_data->threadinterface->Init (); user_data->threadinterface->Init ();
_cygtls::init (); _cygtls::init ();
/* Initialize events */
events_init ();
tty_list::init_session (); tty_list::init_session ();
_main_tls = &_my_tls; _main_tls = &_my_tls;
@ -843,8 +840,6 @@ dll_crt0_1 (void *)
strace.microseconds (); strace.microseconds ();
#endif #endif
create_signal_arrived (); /* FIXME: move into wait_sig? */
/* Initialize debug muto, if DLL is built with --enable-debugging. /* Initialize debug muto, if DLL is built with --enable-debugging.
Need to do this before any helper threads start. */ Need to do this before any helper threads start. */
debug_init (); debug_init ();

View File

@ -19,8 +19,8 @@ details. */
#include <syslog.h> #include <syslog.h>
#include <wchar.h> #include <wchar.h>
#include "pinfo.h"
#include "cygtls.h" #include "cygtls.h"
#include "pinfo.h"
#include "sigproc.h" #include "sigproc.h"
#include "shared_info.h" #include "shared_info.h"
#include "perprocess.h" #include "perprocess.h"
@ -31,7 +31,6 @@ details. */
#include "child_info.h" #include "child_info.h"
#include "ntdll.h" #include "ntdll.h"
#include "exception.h" #include "exception.h"
#include "cygwait.h"
#define CALL_HANDLER_RETRY_OUTER 10 #define CALL_HANDLER_RETRY_OUTER 10
#define CALL_HANDLER_RETRY_INNER 10 #define CALL_HANDLER_RETRY_INNER 10
@ -47,7 +46,6 @@ static BOOL WINAPI ctrl_c_handler (DWORD);
/* This is set to indicate that we have already exited. */ /* This is set to indicate that we have already exited. */
static NO_COPY int exit_already = 0; static NO_COPY int exit_already = 0;
static muto NO_COPY mask_sync;
NO_COPY static struct NO_COPY static struct
{ {
@ -710,11 +708,11 @@ handle_sigsuspend (sigset_t tempmask)
{ {
sigset_t oldmask = _my_tls.sigmask; // Remember for restoration sigset_t oldmask = _my_tls.sigmask; // Remember for restoration
set_signal_mask (tempmask, _my_tls.sigmask); set_signal_mask (_my_tls.sigmask, tempmask);
sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask); sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask);
pthread_testcancel (); pthread_testcancel ();
cancelable_wait (signal_arrived, LARGE_NULL, cw_cancel | cw_cancel_self); cancelable_wait (NULL, cw_infinite, cw_cancel | cw_cancel_self | cw_sig_eintr);
set_sig_errno (EINTR); // Per POSIX set_sig_errno (EINTR); // Per POSIX
@ -747,8 +745,7 @@ sig_handle_tty_stop (int sig)
sigproc_printf ("process %d stopped by signal %d", myself->pid, sig); sigproc_printf ("process %d stopped by signal %d", myself->pid, sig);
HANDLE w4[2]; HANDLE w4[2];
w4[0] = sigCONT; w4[0] = sigCONT;
w4[1] = signal_arrived; switch (cancelable_wait (sigCONT, cw_infinite, cw_sig_eintr))
switch (WaitForMultipleObjects (2, w4, TRUE, INFINITE))
{ {
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
case WAIT_OBJECT_0 + 1: case WAIT_OBJECT_0 + 1:
@ -804,20 +801,11 @@ _cygtls::interrupt_setup (int sig, void *handler, struct sigaction& siga)
this->sig = sig; // Should always be last thing set to avoid a race this->sig = sig; // Should always be last thing set to avoid a race
if (!event) if (signal_arrived)
threadkill = false; SetEvent (signal_arrived);
else
{
HANDLE h = event;
event = NULL;
SetEvent (h);
}
/* Clear any waiting threads prior to dispatching to handler function */
int res = SetEvent (signal_arrived); // For an EINTR case
proc_subproc (PROC_CLEARWAIT, 1); proc_subproc (PROC_CLEARWAIT, 1);
sigproc_printf ("armed signal_arrived %p, signal %d, res %d", signal_arrived, sigproc_printf ("armed signal_arrived %p, signal %d", signal_arrived, sig);
sig, res);
} }
extern "C" void __stdcall extern "C" void __stdcall
@ -1021,7 +1009,7 @@ ctrl_c_handler (DWORD type)
extern "C" void __stdcall extern "C" void __stdcall
set_process_mask (sigset_t newmask) set_process_mask (sigset_t newmask)
{ {
set_signal_mask (newmask, _my_tls.sigmask); set_signal_mask (_my_tls.sigmask, newmask);
} }
extern "C" int extern "C" int
@ -1034,11 +1022,9 @@ sighold (int sig)
syscall_printf ("signal %d out of range", sig); syscall_printf ("signal %d out of range", sig);
return -1; return -1;
} }
mask_sync.acquire (INFINITE);
sigset_t mask = _my_tls.sigmask; sigset_t mask = _my_tls.sigmask;
sigaddset (&mask, sig); sigaddset (&mask, sig);
set_signal_mask (mask, _my_tls.sigmask); set_signal_mask (_my_tls.sigmask, mask);
mask_sync.release ();
return 0; return 0;
} }
@ -1052,11 +1038,9 @@ sigrelse (int sig)
syscall_printf ("signal %d out of range", sig); syscall_printf ("signal %d out of range", sig);
return -1; return -1;
} }
mask_sync.acquire (INFINITE);
sigset_t mask = _my_tls.sigmask; sigset_t mask = _my_tls.sigmask;
sigdelset (&mask, sig); sigdelset (&mask, sig);
set_signal_mask (mask, _my_tls.sigmask); set_signal_mask (_my_tls.sigmask, mask);
mask_sync.release ();
return 0; return 0;
} }
@ -1074,7 +1058,6 @@ sigset (int sig, _sig_func_ptr func)
return (_sig_func_ptr) SIG_ERR; return (_sig_func_ptr) SIG_ERR;
} }
mask_sync.acquire (INFINITE);
sigset_t mask = _my_tls.sigmask; sigset_t mask = _my_tls.sigmask;
/* If sig was in the signal mask return SIG_HOLD, otherwise return the /* If sig was in the signal mask return SIG_HOLD, otherwise return the
previous disposition. */ previous disposition. */
@ -1093,8 +1076,7 @@ sigset (int sig, _sig_func_ptr func)
signal (sig, func); signal (sig, func);
sigdelset (&mask, sig); sigdelset (&mask, sig);
} }
set_signal_mask (mask, _my_tls.sigmask); set_signal_mask (_my_tls.sigmask, mask);
mask_sync.release ();
return prev; return prev;
} }
@ -1109,7 +1091,6 @@ sigignore (int sig)
extern "C" sigset_t extern "C" sigset_t
set_process_mask_delta () set_process_mask_delta ()
{ {
mask_sync.acquire (INFINITE);
sigset_t newmask, oldmask; sigset_t newmask, oldmask;
if (_my_tls.deltamask & SIG_NONMASKABLE) if (_my_tls.deltamask & SIG_NONMASKABLE)
@ -1120,28 +1101,22 @@ set_process_mask_delta ()
sigproc_printf ("oldmask %p, newmask %p, deltamask %p", oldmask, newmask, sigproc_printf ("oldmask %p, newmask %p, deltamask %p", oldmask, newmask,
_my_tls.deltamask); _my_tls.deltamask);
_my_tls.sigmask = newmask; _my_tls.sigmask = newmask;
mask_sync.release ();
return oldmask; return oldmask;
} }
/* Set the signal mask for this process. /* Set the signal mask for this process.
Note that some signals are unmaskable, as in UNIX. */ Note that some signals are unmaskable, as in UNIX. */
extern "C" void __stdcall
set_signal_mask (sigset_t newmask, sigset_t& oldmask) void
set_signal_mask (sigset_t& setmask, sigset_t newmask)
{ {
#ifdef CGF
if (&_my_tls == _sig_tls)
small_printf ("********* waiting in signal thread\n");
#endif
mask_sync.acquire (INFINITE);
newmask &= ~SIG_NONMASKABLE; newmask &= ~SIG_NONMASKABLE;
sigset_t mask_bits = oldmask & ~newmask; sigset_t mask_bits = setmask & ~newmask;
sigproc_printf ("oldmask %p, newmask %p, mask_bits %p", oldmask, newmask, sigproc_printf ("setmask %p, newmask %p, mask_bits %p", setmask, newmask,
mask_bits); mask_bits);
oldmask = newmask; setmask = newmask;
if (mask_bits) if (mask_bits)
sig_dispatch_pending (true); sig_dispatch_pending (true);
mask_sync.release ();
} }
int __stdcall int __stdcall
@ -1184,17 +1159,23 @@ sigpacket::process ()
myself->rusage_self.ru_nsignals++; myself->rusage_self.ru_nsignals++;
bool masked; void *handler = (void *) thissig.sa_handler;
void *handler; if (handler == SIG_IGN)
if (!have_execed || (void *) thissig.sa_handler == (void *) SIG_IGN) {
handler = (void *) thissig.sa_handler; sigproc_printf ("signal %d ignored", si.si_signo);
else if (tls) goto done;
return 1; }
else
if (have_execed)
handler = NULL; handler = NULL;
_cygtls *use_tls = tls ?: _main_tls; if (tls)
sigproc_printf ("tls %p, use_tls %p", tls, use_tls); sigproc_printf ("using tls %p", tls);
else
{
tls = _main_tls;
sigproc_printf ("using main tls %p", _main_tls);
}
if (si.si_signo == SIGKILL) if (si.si_signo == SIGKILL)
goto exit_sig; goto exit_sig;
@ -1204,30 +1185,12 @@ sigpacket::process ()
goto stop; goto stop;
} }
bool insigwait_mask; if (sigismember (&tls->sigwait_mask, si.si_signo))
if ((masked = ISSTATE (myself, PID_STOPPED)))
insigwait_mask = false;
else if (tls)
insigwait_mask = sigismember (&tls->sigwait_mask, si.si_signo);
else if (!(tls = _cygtls::find_tls (si.si_signo)))
insigwait_mask = false;
else
{ {
use_tls = tls; tls->sigwait_mask = 0;
insigwait_mask = true; goto dosig;
} }
if (sigismember (&tls->sigmask, si.si_signo) || ISSTATE (myself, PID_STOPPED))
if (insigwait_mask)
goto thread_specific;
if (masked)
/* nothing to do */;
else if (sigismember (mask, si.si_signo))
masked = true;
else if (tls)
masked = sigismember (&tls->sigmask, si.si_signo);
if (masked)
{ {
sigproc_printf ("signal %d blocked", si.si_signo); sigproc_printf ("signal %d blocked", si.si_signo);
rc = -1; rc = -1;
@ -1240,14 +1203,12 @@ sigpacket::process ()
if (handler == (void *) SIG_DFL) if (handler == (void *) SIG_DFL)
{ {
if (insigwait_mask)
goto thread_specific;
if (si.si_signo == SIGCHLD || si.si_signo == SIGIO || si.si_signo == SIGCONT || si.si_signo == SIGWINCH if (si.si_signo == SIGCHLD || si.si_signo == SIGIO || si.si_signo == SIGCONT || si.si_signo == SIGWINCH
|| si.si_signo == SIGURG) || si.si_signo == SIGURG)
{ {
sigproc_printf ("default signal %d ignored", si.si_signo); sigproc_printf ("default signal %d ignored", si.si_signo);
if (continue_now) if (continue_now)
SetEvent (signal_arrived); SetEvent (tls->signal_arrived);
goto done; goto done;
} }
@ -1257,16 +1218,9 @@ sigpacket::process ()
goto exit_sig; goto exit_sig;
} }
if (handler == (void *) SIG_IGN)
{
sigproc_printf ("signal %d ignored", si.si_signo);
goto done;
}
if (handler == (void *) SIG_ERR) if (handler == (void *) SIG_ERR)
goto exit_sig; goto exit_sig;
use_tls->set_siginfo (this);
goto dosig; goto dosig;
stop: stop:
@ -1277,33 +1231,19 @@ stop:
thissig = dummy; thissig = dummy;
dosig: dosig:
tls->set_siginfo (this);
/* Dispatch to the appropriate function. */ /* Dispatch to the appropriate function. */
sigproc_printf ("signal %d, about to call %p", si.si_signo, handler); sigproc_printf ("signal %d, signal handler %p", si.si_signo, handler);
rc = setup_handler (si.si_signo, handler, thissig, use_tls); rc = setup_handler (si.si_signo, handler, thissig, tls);
done: done:
tls = use_tls;
if (continue_now) if (continue_now)
SetEvent (sigCONT); SetEvent (sigCONT);
sigproc_printf ("returning %d", rc); sigproc_printf ("returning %d", rc);
return rc; return rc;
thread_specific:
use_tls->sig = si.si_signo;
use_tls->set_siginfo (this);
use_tls->func = NULL;
sigproc_printf ("releasing sigwait for thread");
SetEvent (use_tls->event);
goto done;
exit_sig: exit_sig:
use_tls->signal_exit (si.si_signo); /* never returns */ tls->signal_exit (si.si_signo); /* never returns */
}
void
events_init ()
{
mask_sync.init ("mask_sync");
} }
void void
@ -1321,23 +1261,7 @@ _cygtls::call_signal_handler ()
lock (); lock ();
if (sig) if (sig)
pop (); pop ();
else if (this != _main_tls) else
{
_main_tls->lock ();
if (_main_tls->sig && _main_tls->incyg)
{
paranoid_printf ("Redirecting to main_tls signal %d", _main_tls->sig);
sig = _main_tls->sig;
sa_flags = _main_tls->sa_flags;
func = _main_tls->func;
infodata = _main_tls->infodata;
_main_tls->pop ();
_main_tls->sig = 0;
}
_main_tls->unlock ();
}
if (!sig)
break; break;
debug_only_printf ("dealing with signal %d", sig); debug_only_printf ("dealing with signal %d", sig);
@ -1364,7 +1288,7 @@ _cygtls::call_signal_handler ()
sigact (thissig, &thissi, NULL); sigact (thissig, &thissi, NULL);
} }
incyg = true; incyg = true;
set_signal_mask (this_oldmask, _my_tls.sigmask); set_signal_mask (_my_tls.sigmask, this_oldmask);
if (this_errno >= 0) if (this_errno >= 0)
set_errno (this_errno); set_errno (this_errno);
} }

View File

@ -125,9 +125,7 @@ get_inet_addr (const struct sockaddr *in, int inlen,
some greedy Win32 application. Therefore we should never wait some greedy Win32 application. Therefore we should never wait
endlessly without checking for signals and thread cancel event. */ endlessly without checking for signals and thread cancel event. */
pthread_testcancel (); pthread_testcancel ();
/* Using IsEventSignalled like this is racy since another thread could if (cancelable_wait (NULL, cw_nowait, cw_sig_eintr) == WAIT_SIGNALED
be waiting for signal_arrived. */
if (IsEventSignalled (signal_arrived)
&& !_my_tls.call_signal_handler ()) && !_my_tls.call_signal_handler ())
{ {
set_errno (EINTR); set_errno (EINTR);
@ -659,7 +657,8 @@ fhandler_socket::wait_for_events (const long event_mask, const DWORD flags)
return SOCKET_ERROR; return SOCKET_ERROR;
} }
WSAEVENT ev[2] = { wsock_evt, signal_arrived }; WSAEVENT ev[2] = { wsock_evt };
set_thread_waiting here (ev[1]);
switch (WSAWaitForMultipleEvents (2, ev, FALSE, 50, FALSE)) switch (WSAWaitForMultipleEvents (2, ev, FALSE, 50, FALSE))
{ {
case WSA_WAIT_TIMEOUT: case WSA_WAIT_TIMEOUT:
@ -1778,7 +1777,7 @@ fhandler_socket::close ()
res = -1; res = -1;
break; break;
} }
if (WaitForSingleObject (signal_arrived, 10) == WAIT_OBJECT_0) if (cygwait (10) == WAIT_SIGNALED)
{ {
set_errno (EINTR); set_errno (EINTR);
res = -1; res = -1;

View File

@ -1147,26 +1147,13 @@ mtinfo::initialize ()
inline bool inline bool
fhandler_dev_tape::_lock (bool cancelable) fhandler_dev_tape::_lock (bool cancelable)
{ {
HANDLE w4[3] = { mt_mtx, signal_arrived, NULL };
DWORD cnt = 2;
if (cancelable && (w4[2] = pthread::get_cancel_event ()) != NULL)
cnt = 3;
/* O_NONBLOCK is only valid in a read or write call. Only those are /* O_NONBLOCK is only valid in a read or write call. Only those are
cancelable. */ cancelable. */
DWORD timeout = cancelable && is_nonblocking () ? 0 : INFINITE; DWORD timeout = cancelable && is_nonblocking () ? 0 : INFINITE;
restart: switch (cancelable_wait (mt_mtx, timeout, cw_sig | cw_cancel | cw_cancel_self))
switch (WaitForMultipleObjects (cnt, w4, FALSE, timeout))
{ {
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
return true; return true;
case WAIT_OBJECT_0 + 1:
if (_my_tls.call_signal_handler ())
goto restart;
set_errno (EINTR);
return false;
case WAIT_OBJECT_0 + 2:
pthread::static_cancel_self ();
/*NOTREACHED*/
case WAIT_TIMEOUT: case WAIT_TIMEOUT:
set_errno (EAGAIN); set_errno (EAGAIN);
return false; return false;

View File

@ -204,7 +204,7 @@ fhandler_termios::bg_check (int sig)
{ {
/* Don't raise a SIGTT* signal if we have already been /* Don't raise a SIGTT* signal if we have already been
interrupted by another signal. */ interrupted by another signal. */
if (WaitForSingleObject (signal_arrived, 0) != WAIT_OBJECT_0) if (cygwait ((DWORD) 0) != WAIT_SIGNALED)
{ {
siginfo_t si = {0}; siginfo_t si = {0};
si.si_signo = sig; si.si_signo = sig;

View File

@ -281,7 +281,7 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on
goto out; goto out;
} }
pthread_testcancel (); pthread_testcancel ();
if (WaitForSingleObject (signal_arrived, 10) == WAIT_OBJECT_0 if (cancelable_wait (NULL, 10, cw_sig_eintr) == WAIT_SIGNALED
&& !_my_tls.call_signal_handler ()) && !_my_tls.call_signal_handler ())
{ {
set_errno (EINTR); set_errno (EINTR);

View File

@ -96,43 +96,47 @@ fhandler_windows::read (void *buf, size_t& len)
return; return;
} }
HANDLE w4[3] = { get_handle (), signal_arrived, NULL }; HANDLE w4[3] = { get_handle (), };
set_thread_waiting here (w4[1]);
DWORD cnt = 2; DWORD cnt = 2;
if ((w4[cnt] = pthread::get_cancel_event ()) != NULL) if ((w4[cnt] = pthread::get_cancel_event ()) != NULL)
++cnt; ++cnt;
restart: for (;;)
switch (MsgWaitForMultipleObjectsEx (cnt, w4,
is_nonblocking () ? 0 : INFINITE,
QS_ALLINPUT | QS_ALLPOSTMESSAGE,
MWMO_INPUTAVAILABLE))
{ {
case WAIT_OBJECT_0: switch (MsgWaitForMultipleObjectsEx (cnt, w4,
if (!PeekMessageW (ptr, hWnd_, 0, 0, PM_REMOVE)) is_nonblocking () ? 0 : INFINITE,
QS_ALLINPUT | QS_ALLPOSTMESSAGE,
MWMO_INPUTAVAILABLE))
{ {
case WAIT_OBJECT_0:
if (!PeekMessageW (ptr, hWnd_, 0, 0, PM_REMOVE))
{
len = (size_t) -1;
__seterrno ();
}
else if (ptr->message == WM_QUIT)
len = 0;
else
len = sizeof (MSG);
break;
case WAIT_OBJECT_0 + 1:
if (_my_tls.call_signal_handler ())
continue;
len = (size_t) -1;
set_errno (EINTR);
break;
case WAIT_OBJECT_0 + 2:
pthread::static_cancel_self ();
break;
case WAIT_TIMEOUT:
len = (size_t) -1;
set_errno (EAGAIN);
break;
default:
len = (size_t) -1; len = (size_t) -1;
__seterrno (); __seterrno ();
break;
} }
else if (ptr->message == WM_QUIT)
len = 0;
else
len = sizeof (MSG);
break;
case WAIT_OBJECT_0 + 1:
if (_my_tls.call_signal_handler ())
goto restart;
len = (size_t) -1;
set_errno (EINTR);
break;
case WAIT_OBJECT_0 + 2:
pthread::static_cancel_self ();
break;
case WAIT_TIMEOUT:
len = (size_t) -1;
set_errno (EAGAIN);
break;
default:
len = (size_t) -1;
__seterrno ();
break; break;
} }
} }

View File

@ -1247,7 +1247,7 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
timeout = 100L; timeout = 100L;
DWORD WAIT_SIGNAL_ARRIVED = WAIT_OBJECT_0 + wait_count; DWORD WAIT_SIGNAL_ARRIVED = WAIT_OBJECT_0 + wait_count;
w4[wait_count++] = signal_arrived; set_thread_waiting here (w4[wait_count++]);
DWORD WAIT_THREAD_CANCELED = WAIT_TIMEOUT + 1; DWORD WAIT_THREAD_CANCELED = WAIT_TIMEOUT + 1;
HANDLE cancel_event = pthread::get_cancel_event (); HANDLE cancel_event = pthread::get_cancel_event ();

View File

@ -202,8 +202,6 @@ _sigdelayed:
pushl \$_sigreturn # where to return pushl \$_sigreturn # where to return
pushl $tls::func(%ebx) # user-supplied signal func pushl $tls::func(%ebx) # user-supplied signal func
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 movl \$0,$tls::sig(%ebx) # zero the signal number as a
# flag to the signal handler thread # flag to the signal handler thread
# that it is ok to set up sigsave # that it is ok to set up sigsave

View File

@ -14,10 +14,10 @@ my $struct = '';
my @fields = (); my @fields = ();
my $def = ''; my $def = '';
$tls = join('', <TLS>); $tls = join('', <TLS>);
$tls =~ s/\A.*\n#pragma once\n//os;
$tls =~ s/\n[^\n]*gentls_offsets[^\n]*\n(.+)\Z/$1/os; $tls =~ s/\n[^\n]*gentls_offsets[^\n]*\n(.+)\Z/$1/os;
my $pre = $`; my $pre = $`;
substr($tls, 0, length($pre)) = ''; substr($tls, 0, length($pre)) = '';
$pre =~ s/\n#ifndef _[^\n]+\n/\n/os;
$pre .= "\n//*/"; $pre .= "\n//*/";
$tls =~ s%/\*\s*gentls_offsets.*?/\*\s*gentls_offsets\s*\*/%%ogs; $tls =~ s%/\*\s*gentls_offsets.*?/\*\s*gentls_offsets\s*\*/%%ogs;
foreach ($tls =~ /^.*\n/mg) { foreach ($tls =~ /^.*\n/mg) {

View File

@ -9,8 +9,7 @@
Cygwin license. Please consult the file "CYGWIN_LICENSE" for Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */ details. */
#ifndef _NTDLL_H #pragma once
#define _NTDLL_H 1
#ifndef __MINGW64_VERSION_MAJOR #ifndef __MINGW64_VERSION_MAJOR
# include <ddk/ntstatus.h> # include <ddk/ntstatus.h>
@ -1425,4 +1424,3 @@ extern "C"
} }
} }
#endif #endif
#endif /*_NTDLL_H*/

View File

@ -152,9 +152,9 @@ ppoll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts,
? -1 ? -1
: (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000); : (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000);
if (sigmask) if (sigmask)
set_signal_mask (*sigmask, _my_tls.sigmask); set_signal_mask (_my_tls.sigmask, *sigmask);
int ret = poll (fds, nfds, timeout); int ret = poll (fds, nfds, timeout);
if (sigmask) if (sigmask)
set_signal_mask (oldset, _my_tls.sigmask); set_signal_mask (_my_tls.sigmask, oldset);
return ret; return ret;
} }

View File

@ -119,14 +119,12 @@ ipc_mutex_init (HANDLE *pmtx, const char *name)
static int static int
ipc_mutex_lock (HANDLE mtx) ipc_mutex_lock (HANDLE mtx)
{ {
HANDLE h[2] = { mtx, signal_arrived }; switch (cancelable_wait (mtx, cw_infinite, cw_sig_eintr | cw_cancel | cw_cancel_self))
switch (WaitForMultipleObjects (2, h, FALSE, INFINITE))
{ {
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
case WAIT_ABANDONED_0: case WAIT_ABANDONED_0:
return 0; return 0;
case WAIT_OBJECT_0 + 1: case WAIT_SIGNALED:
set_errno (EINTR); set_errno (EINTR);
return 1; return 1;
default: default:
@ -174,11 +172,12 @@ ipc_cond_init (HANDLE *pevt, const char *name, char sr)
static int static int
ipc_cond_timedwait (HANDLE evt, HANDLE mtx, const struct timespec *abstime) ipc_cond_timedwait (HANDLE evt, HANDLE mtx, const struct timespec *abstime)
{ {
HANDLE w4[4] = { evt, signal_arrived, NULL, NULL }; HANDLE w4[4] = { evt, };
DWORD cnt = 2; DWORD cnt = 2;
DWORD timer_idx = 0; DWORD timer_idx = 0;
int ret = 0; int ret = 0;
set_thread_waiting here (w4[1]);
if ((w4[cnt] = pthread::get_cancel_event ()) != NULL) if ((w4[cnt] = pthread::get_cancel_event ()) != NULL)
++cnt; ++cnt;
if (abstime) if (abstime)

View File

@ -9,8 +9,7 @@ This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */ details. */
#ifndef _SECURITY_H #pragma once
#define _SECURITY_H
#include <accctrl.h> #include <accctrl.h>
@ -513,5 +512,3 @@ sec_user (SECURITY_ATTRIBUTES *sa_buf, PSID sid1, PSID sid2 = NULL,
{ {
return __sec_user (sa_buf, sid1, sid2, access2, TRUE); return __sec_user (sa_buf, sid1, sid2, access2, TRUE);
} }
#endif /*_SECURITY_H*/

View File

@ -100,20 +100,28 @@ cygwin_select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
select_printf ("select(%d, %p, %p, %p, %p)", maxfds, readfds, writefds, exceptfds, to); select_printf ("select(%d, %p, %p, %p, %p)", maxfds, readfds, writefds, exceptfds, to);
pthread_testcancel (); pthread_testcancel ();
int res;
/* Convert to milliseconds or INFINITE if to == NULL */ if (maxfds < 0)
DWORD ms = to ? (to->tv_sec * 1000) + (to->tv_usec / 1000) : INFINITE; {
if (ms == 0 && to->tv_usec) set_errno (EINVAL);
ms = 1; /* At least 1 ms granularity */ res = -1;
}
if (to)
select_printf ("to->tv_sec %d, to->tv_usec %d, ms %d", to->tv_sec, to->tv_usec, ms);
else else
select_printf ("to NULL, ms %x", ms); {
/* Convert to milliseconds or INFINITE if to == NULL */
DWORD ms = to ? (to->tv_sec * 1000) + (to->tv_usec / 1000) : INFINITE;
if (ms == 0 && to->tv_usec)
ms = 1; /* At least 1 ms granularity */
int res = select (maxfds, readfds ?: allocfd_set (maxfds), if (to)
select_printf ("to->tv_sec %d, to->tv_usec %d, ms %d", to->tv_sec, to->tv_usec, ms);
else
select_printf ("to NULL, ms %x", ms);
res = select (maxfds, readfds ?: allocfd_set (maxfds),
writefds ?: allocfd_set (maxfds), writefds ?: allocfd_set (maxfds),
exceptfds ?: allocfd_set (maxfds), ms); exceptfds ?: allocfd_set (maxfds), ms);
}
syscall_printf ("%R = select(%d, %p, %p, %p, %p)", res, maxfds, readfds, syscall_printf ("%R = select(%d, %p, %p, %p, %p)", res, maxfds, readfds,
writefds, exceptfds, to); writefds, exceptfds, to);
return res; return res;
@ -179,6 +187,7 @@ select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
else else
res = sel.wait (r, w, e, ms); /* wait for an fd to become res = sel.wait (r, w, e, ms); /* wait for an fd to become
become active or time out */ become active or time out */
select_printf ("res %d", res);
if (res >= 0) if (res >= 0)
{ {
copyfd_set (readfds, r, maxfds); copyfd_set (readfds, r, maxfds);
@ -197,7 +206,10 @@ select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
select_printf ("recalculating ms"); select_printf ("recalculating ms");
LONGLONG now = gtod.msecs (); LONGLONG now = gtod.msecs ();
if (now > (start_time + ms)) if (now > (start_time + ms))
select_printf ("timed out after verification"); {
select_printf ("timed out after verification");
res = select_stuff::select_error;
}
else else
{ {
ms -= (now - start_time); ms -= (now - start_time);
@ -228,11 +240,11 @@ pselect(int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
tv.tv_usec = ts->tv_nsec / 1000; tv.tv_usec = ts->tv_nsec / 1000;
} }
if (set) if (set)
set_signal_mask (*set, _my_tls.sigmask); set_signal_mask (_my_tls.sigmask, *set);
int ret = cygwin_select (maxfds, readfds, writefds, exceptfds, int ret = cygwin_select (maxfds, readfds, writefds, exceptfds,
ts ? &tv : NULL); ts ? &tv : NULL);
if (set) if (set)
set_signal_mask (oldset, _my_tls.sigmask); set_signal_mask (_my_tls.sigmask, oldset);
return ret; return ret;
} }
@ -320,7 +332,7 @@ select_stuff::wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
select_record *s = &start; select_record *s = &start;
DWORD m = 0; DWORD m = 0;
w4[m++] = signal_arrived; /* Always wait for the arrival of a signal. */ set_thread_waiting here (w4[m++]);
if ((w4[m] = pthread::get_cancel_event ()) != NULL) if ((w4[m] = pthread::get_cancel_event ()) != NULL)
m++; m++;

View File

@ -120,12 +120,9 @@ clock_nanosleep (clockid_t clk_id, int flags, const struct timespec *rqtp,
syscall_printf ("clock_nanosleep (%ld.%09ld)", rqtp->tv_sec, rqtp->tv_nsec); syscall_printf ("clock_nanosleep (%ld.%09ld)", rqtp->tv_sec, rqtp->tv_nsec);
int rc = cancelable_wait (signal_arrived, &timeout); int rc = cancelable_wait (NULL, &timeout, cw_sig | cw_cancel | cw_cancel_self);
if (rc == WAIT_OBJECT_0) if (rc == WAIT_SIGNALED)
{ res = EINTR;
_my_tls.call_signal_handler ();
res = EINTR;
}
/* according to POSIX, rmtp is used only if !abstime */ /* according to POSIX, rmtp is used only if !abstime */
if (rmtp && !abstime) if (rmtp && !abstime)
@ -226,7 +223,7 @@ handle_sigprocmask (int how, const sigset_t *set, sigset_t *oldset, sigset_t& op
newmask = *set; newmask = *set;
break; break;
} }
set_signal_mask (newmask, opmask); set_signal_mask (opmask, newmask);
} }
return 0; return 0;
} }
@ -379,7 +376,7 @@ abort (void)
sigset_t sig_mask; sigset_t sig_mask;
sigfillset (&sig_mask); sigfillset (&sig_mask);
sigdelset (&sig_mask, SIGABRT); sigdelset (&sig_mask, SIGABRT);
set_signal_mask (sig_mask, _my_tls.sigmask); set_signal_mask (_my_tls.sigmask, sig_mask);
raise (SIGABRT); raise (SIGABRT);
_my_tls.call_signal_handler (); /* Call any signal handler */ _my_tls.call_signal_handler (); /* Call any signal handler */
@ -568,21 +565,18 @@ extern "C" int
sigwaitinfo (const sigset_t *set, siginfo_t *info) sigwaitinfo (const sigset_t *set, siginfo_t *info)
{ {
pthread_testcancel (); pthread_testcancel ();
HANDLE h;
h = _my_tls.event = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
if (!h)
{
__seterrno ();
return -1;
}
_my_tls.sigwait_mask = *set; myfault efault;
if (efault.faulted (EFAULT))
return EFAULT;
set_signal_mask (_my_tls.sigwait_mask, *set);
sig_dispatch_pending (true); sig_dispatch_pending (true);
int res; int res;
switch (WaitForSingleObject (h, INFINITE)) switch (cancelable_wait (NULL, cw_infinite, cw_sig | cw_cancel | cw_cancel_self))
{ {
case WAIT_OBJECT_0: case WAIT_SIGNALED:
if (!sigismember (set, _my_tls.infodata.si_signo)) if (!sigismember (set, _my_tls.infodata.si_signo))
{ {
set_errno (EINTR); set_errno (EINTR);
@ -593,6 +587,7 @@ sigwaitinfo (const sigset_t *set, siginfo_t *info)
if (info) if (info)
*info = _my_tls.infodata; *info = _my_tls.infodata;
res = _my_tls.infodata.si_signo; res = _my_tls.infodata.si_signo;
/* FIXME: Is this right? */
InterlockedExchange ((LONG *) &_my_tls.sig, (LONG) 0); InterlockedExchange ((LONG *) &_my_tls.sig, (LONG) 0);
} }
break; break;
@ -601,8 +596,6 @@ sigwaitinfo (const sigset_t *set, siginfo_t *info)
res = -1; res = -1;
} }
_my_tls.event = NULL;
CloseHandle (h);
sigproc_printf ("returning signal %d", res); sigproc_printf ("returning signal %d", res);
return res; return res;
} }

View File

@ -43,9 +43,6 @@ int __sp_ln;
char NO_COPY myself_nowait_dummy[1] = {'0'};// Flag to sig_send that signal goes to char NO_COPY myself_nowait_dummy[1] = {'0'};// Flag to sig_send that signal goes to
// current process but no wait is required // current process but no wait is required
HANDLE NO_COPY signal_arrived; // Event signaled when a signal has
// resulted in a user-specified
// function call
#define Static static NO_COPY #define Static static NO_COPY
@ -518,17 +515,6 @@ sig_dispatch_pending (bool fast)
sig_send (myself, fast ? __SIGFLUSHFAST : __SIGFLUSH); sig_send (myself, fast ? __SIGFLUSHFAST : __SIGFLUSH);
} }
void __stdcall
create_signal_arrived ()
{
if (signal_arrived)
return;
/* local event signaled when main thread has been dispatched
to a signal handler function. */
signal_arrived = CreateEvent (&sec_none_nih, false, false, NULL);
ProtectHandle (signal_arrived);
}
/* Signal thread initialization. Called from dll_crt0_1. /* Signal thread initialization. Called from dll_crt0_1.
This routine starts the signal handling thread. */ This routine starts the signal handling thread. */
void __stdcall void __stdcall
@ -1233,7 +1219,7 @@ stopped_or_terminated (waitq *parent_w, _pinfo *child)
int might_match; int might_match;
waitq *w = parent_w->next; waitq *w = parent_w->next;
sigproc_printf ("considering pid %d", child->pid); sigproc_printf ("considering pid %d, pgid %d, w->pid %d", child->pid, child->pgid, w->pid);
if (w->pid == -1) if (w->pid == -1)
might_match = 1; might_match = 1;
else if (w->pid == 0) else if (w->pid == 0)

View File

@ -58,13 +58,11 @@ struct sigpacket
int __stdcall process () __attribute__ ((regparm (1))); int __stdcall process () __attribute__ ((regparm (1)));
}; };
extern HANDLE signal_arrived;
extern HANDLE sigCONT; extern HANDLE sigCONT;
void __stdcall sig_dispatch_pending (bool fast = false); void __stdcall sig_dispatch_pending (bool fast = false)
#ifdef EXITCODE_SET __attribute__ ((regparm (1)));
extern "C" void __stdcall set_signal_mask (sigset_t newmask, sigset_t&); void set_signal_mask (sigset_t&, sigset_t) __attribute__ ((regparm (2)));
#endif
int __stdcall handle_sigprocmask (int sig, const sigset_t *set, int __stdcall handle_sigprocmask (int sig, const sigset_t *set,
sigset_t *oldset, sigset_t& opmask) sigset_t *oldset, sigset_t& opmask)
__attribute__ ((regparm (3))); __attribute__ ((regparm (3)));
@ -86,7 +84,6 @@ int __stdcall sig_send (_pinfo *, siginfo_t&, class _cygtls *tls = NULL) __attri
int __stdcall sig_send (_pinfo *, int) __attribute__ ((regparm (2))); int __stdcall sig_send (_pinfo *, int) __attribute__ ((regparm (2)));
void __stdcall signal_fixup_after_exec (); void __stdcall signal_fixup_after_exec ();
void __stdcall sigalloc (); void __stdcall sigalloc ();
void __stdcall create_signal_arrived ();
int kill_pgrp (pid_t, siginfo_t&); int kill_pgrp (pid_t, siginfo_t&);
int killsys (pid_t, int); int killsys (pid_t, int);

View File

@ -2295,7 +2295,7 @@ retry:
{ {
debug_printf ("status %p", status); debug_printf ("status %p", status);
if (status == STATUS_SHARING_VIOLATION if (status == STATUS_SHARING_VIOLATION
&& WaitForSingleObject (signal_arrived, 10L) != WAIT_OBJECT_0) && cygwait (10L) != WAIT_SIGNALED)
{ {
/* Typical BLODA problem. Some virus scanners check newly generated /* Typical BLODA problem. Some virus scanners check newly generated
files and while doing that disallow DELETE access. That's really files and while doing that disallow DELETE access. That's really

View File

@ -1744,7 +1744,7 @@ pthread_mutex::lock ()
|| !pthread::equal (owner, self)) || !pthread::equal (owner, self))
{ {
/* FIXME: no cancel? */ /* FIXME: no cancel? */
cancelable_wait (win32_obj_id, LARGE_NULL, cw_sig); cancelable_wait (win32_obj_id, cw_infinite, cw_sig);
set_owner (self); set_owner (self);
} }
else else
@ -2364,7 +2364,7 @@ pthread::join (pthread_t *thread, void **return_val)
(*thread)->attr.joinable = PTHREAD_CREATE_DETACHED; (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
(*thread)->mutex.unlock (); (*thread)->mutex.unlock ();
switch (cancelable_wait ((*thread)->win32_obj_id, LARGE_NULL, cw_sig | cw_cancel)) switch (cancelable_wait ((*thread)->win32_obj_id, cw_infinite, cw_sig | cw_cancel))
{ {
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
if (return_val) if (return_val)
@ -3015,10 +3015,7 @@ pthread_kill (pthread_t thread, int sig)
if (!thread->valid) if (!thread->valid)
rval = ESRCH; rval = ESRCH;
else if (sig) else if (sig)
{ rval = sig_send (NULL, si, thread->cygtls);
thread->cygtls->set_threadkill ();
rval = sig_send (NULL, si, thread->cygtls);
}
else else
switch (WaitForSingleObject (thread->win32_obj_id, 0)) switch (WaitForSingleObject (thread->win32_obj_id, 0))
{ {
@ -3501,7 +3498,7 @@ semaphore::_timedwait (const struct timespec *abstime)
int int
semaphore::_wait () semaphore::_wait ()
{ {
switch (cancelable_wait (win32_obj_id, LARGE_NULL, cw_cancel | cw_cancel_self | cw_sig_eintr)) switch (cancelable_wait (win32_obj_id, cw_infinite, cw_cancel | cw_cancel_self | cw_sig_eintr))
{ {
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
currentvalue--; currentvalue--;

View File

@ -60,7 +60,7 @@ public:
void lock () void lock ()
{ {
if (InterlockedIncrement ((long *) &lock_counter) != 1) if (InterlockedIncrement ((long *) &lock_counter) != 1)
cancelable_wait (win32_obj_id, LARGE_NULL, cw_sig); cancelable_wait (win32_obj_id, cw_infinite, cw_sig);
} }
void unlock () void unlock ()

View File

@ -1,42 +1,42 @@
//;# autogenerated: Do not edit. //;# autogenerated: Do not edit.
//; $tls::sizeof__cygtls = 4048; //; $tls::sizeof__cygtls = 4048;
//; $tls::func = -12700; //; $tls::locals = -12700;
//; $tls::pfunc = 0; //; $tls::plocals = 0;
//; $tls::saved_errno = -12696; //; $tls::local_clib = -11236;
//; $tls::psaved_errno = 4; //; $tls::plocal_clib = 1464;
//; $tls::sa_flags = -12692; //; $tls::__dontuse = -11236;
//; $tls::psa_flags = 8; //; $tls::p__dontuse = 1464;
//; $tls::oldmask = -12688; //; $tls::func = -10148;
//; $tls::poldmask = 12; //; $tls::pfunc = 2552;
//; $tls::deltamask = -12684; //; $tls::saved_errno = -10144;
//; $tls::pdeltamask = 16; //; $tls::psaved_errno = 2556;
//; $tls::event = -12680; //; $tls::sa_flags = -10140;
//; $tls::pevent = 20; //; $tls::psa_flags = 2560;
//; $tls::errno_addr = -12676; //; $tls::oldmask = -10136;
//; $tls::perrno_addr = 24; //; $tls::poldmask = 2564;
//; $tls::sigmask = -12672; //; $tls::deltamask = -10132;
//; $tls::psigmask = 28; //; $tls::pdeltamask = 2568;
//; $tls::sigwait_mask = -12668; //; $tls::errno_addr = -10128;
//; $tls::psigwait_mask = 32; //; $tls::perrno_addr = 2572;
//; $tls::sigwait_info = -12664; //; $tls::sigmask = -10124;
//; $tls::psigwait_info = 36; //; $tls::psigmask = 2576;
//; $tls::thread_context = -12660; //; $tls::sigwait_mask = -10120;
//; $tls::pthread_context = 40; //; $tls::psigwait_mask = 2580;
//; $tls::thread_id = -12448; //; $tls::sigwait_info = -10116;
//; $tls::pthread_id = 252; //; $tls::psigwait_info = 2584;
//; $tls::threadkill = -12444; //; $tls::signal_arrived = -10112;
//; $tls::pthreadkill = 256; //; $tls::psignal_arrived = 2588;
//; $tls::infodata = -12440; //; $tls::signal_waiting = -10108;
//; $tls::pinfodata = 260; //; $tls::psignal_waiting = 2592;
//; $tls::tid = -12292; //; $tls::thread_context = -10104;
//; $tls::ptid = 408; //; $tls::pthread_context = 2596;
//; $tls::local_clib = -12288; //; $tls::thread_id = -9892;
//; $tls::plocal_clib = 412; //; $tls::pthread_id = 2808;
//; $tls::__dontuse = -12288; //; $tls::infodata = -9888;
//; $tls::p__dontuse = 412; //; $tls::pinfodata = 2812;
//; $tls::locals = -11200; //; $tls::tid = -9740;
//; $tls::plocals = 1500; //; $tls::ptid = 2960;
//; $tls::_ctinfo = -9736; //; $tls::_ctinfo = -9736;
//; $tls::p_ctinfo = 2964; //; $tls::p_ctinfo = 2964;
//; $tls::andreas = -9732; //; $tls::andreas = -9732;
@ -59,42 +59,42 @@
//; $tls::pinitialized = 4044; //; $tls::pinitialized = 4044;
//; __DATA__ //; __DATA__
#define tls_func (-12700) #define tls_locals (-12700)
#define tls_pfunc (0) #define tls_plocals (0)
#define tls_saved_errno (-12696) #define tls_local_clib (-11236)
#define tls_psaved_errno (4) #define tls_plocal_clib (1464)
#define tls_sa_flags (-12692) #define tls___dontuse (-11236)
#define tls_psa_flags (8) #define tls_p__dontuse (1464)
#define tls_oldmask (-12688) #define tls_func (-10148)
#define tls_poldmask (12) #define tls_pfunc (2552)
#define tls_deltamask (-12684) #define tls_saved_errno (-10144)
#define tls_pdeltamask (16) #define tls_psaved_errno (2556)
#define tls_event (-12680) #define tls_sa_flags (-10140)
#define tls_pevent (20) #define tls_psa_flags (2560)
#define tls_errno_addr (-12676) #define tls_oldmask (-10136)
#define tls_perrno_addr (24) #define tls_poldmask (2564)
#define tls_sigmask (-12672) #define tls_deltamask (-10132)
#define tls_psigmask (28) #define tls_pdeltamask (2568)
#define tls_sigwait_mask (-12668) #define tls_errno_addr (-10128)
#define tls_psigwait_mask (32) #define tls_perrno_addr (2572)
#define tls_sigwait_info (-12664) #define tls_sigmask (-10124)
#define tls_psigwait_info (36) #define tls_psigmask (2576)
#define tls_thread_context (-12660) #define tls_sigwait_mask (-10120)
#define tls_pthread_context (40) #define tls_psigwait_mask (2580)
#define tls_thread_id (-12448) #define tls_sigwait_info (-10116)
#define tls_pthread_id (252) #define tls_psigwait_info (2584)
#define tls_threadkill (-12444) #define tls_signal_arrived (-10112)
#define tls_pthreadkill (256) #define tls_psignal_arrived (2588)
#define tls_infodata (-12440) #define tls_signal_waiting (-10108)
#define tls_pinfodata (260) #define tls_psignal_waiting (2592)
#define tls_tid (-12292) #define tls_thread_context (-10104)
#define tls_ptid (408) #define tls_pthread_context (2596)
#define tls_local_clib (-12288) #define tls_thread_id (-9892)
#define tls_plocal_clib (412) #define tls_pthread_id (2808)
#define tls___dontuse (-12288) #define tls_infodata (-9888)
#define tls_p__dontuse (412) #define tls_pinfodata (2812)
#define tls_locals (-11200) #define tls_tid (-9740)
#define tls_plocals (1500) #define tls_ptid (2960)
#define tls__ctinfo (-9736) #define tls__ctinfo (-9736)
#define tls_p_ctinfo (2964) #define tls_p_ctinfo (2964)
#define tls_andreas (-9732) #define tls_andreas (-9732)

View File

@ -80,7 +80,7 @@ wait4 (int intpid, int *status, int options, struct rusage *r)
if ((waitfor = w->ev) == NULL) if ((waitfor = w->ev) == NULL)
goto nochildren; goto nochildren;
res = cancelable_wait (waitfor, LARGE_NULL, cw_cancel | cw_cancel_self); res = cancelable_wait (waitfor, cw_infinite, cw_cancel | cw_cancel_self);
sigproc_printf ("%d = cancelable_wait (...)", res); sigproc_printf ("%d = cancelable_wait (...)", res);