handling of call_signal_handler.
* cygwait.h (WAIT_CANCELED): Move here and redefine.
(WAIT_SIGNALED): Ditto.
* thread.h (WAIT_CANCELED): Delete.
(WAIT_SIGNALED): Ditto.
+2012-06-18 Christopher Faylor <me.cygwin2012@cgf.cx>
+
+ * cygwait.cc (cancelable_wait): Mimic old cygwait behavior more closely
+ wrt handling of call_signal_handler.
+ * cygwait.h (WAIT_CANCELED): Move here and redefine.
+ (WAIT_SIGNALED): Ditto.
+ * thread.h (WAIT_CANCELED): Delete.
+ (WAIT_SIGNALED): Ditto.
+
2012-06-18 Corinna Vinschen <corinna@vinschen.de>
* cygheap.cc (init_cygheap::init_installation_root): Rearrange code
blk.gidcnt = 0;
blk.gidlist = NULL;
blk.is_admin = false;
- blk.signal_arrived = signal_arrived;
+ blk.signal_arrived = _my_tls.signal_arrived;
}
#endif /* __INSIDE_CYGWIN__ */
LONG prio = GetThreadPriority (hth);
::SetThreadPriority (hth, THREAD_PRIORITY_BELOW_NORMAL);
- HANDLE w4[2];
- unsigned n = 2;
DWORD howlong = INFINITE;
- w4[0] = sigwait;
- w4[1] = signal_arrived;
/* For a description of the below loop see the end of this file */
for (int i = 0; i < 2; i++)
- switch (res = WaitForMultipleObjects (n, w4, FALSE, howlong))
+ switch (res = cygwait (sigwait, howlong))
{
case WAIT_OBJECT_0:
if (n == 1)
howlong = 50;
break;
- case WAIT_OBJECT_0 + 1:
+ case WAIT_SIGNALED:
n = 1;
if (i--)
howlong = 50;
break;
default:
if (!exiting)
- {
- system_printf ("WFMO failed waiting for cygthread '%s', %E", __name);
- for (unsigned j = 0; j < n; j++)
- switch (WaitForSingleObject (w4[j], 0))
- {
- case WAIT_OBJECT_0:
- case WAIT_TIMEOUT:
- break;
- default:
- system_printf ("%s handle %p is bad", (j ? "signal_arrived" : "semaphore"), w4[j]);
- break;
- }
- api_fatal ("exiting on fatal error");
- }
+ api_fatal ("WFMO failed waiting for cygthread '%s', %E", __name);
break;
}
/* WAIT_OBJECT_0 means that the thread successfully read something,
int sa_flags;
sigset_t oldmask;
sigset_t deltamask;
- HANDLE event;
+ HANDLE signal_arrived;
+ bool waiting;
int *errno_addr;
sigset_t sigmask;
sigset_t sigwait_mask;
#define is_cw_sig_handle (mask & (is_cw_sig | is_cw_sig_eintr))
+TIMER_BASIC_INFORMATION cw_nowait;
+
DWORD
cancelable_wait (HANDLE object, PLARGE_INTEGER timeout, unsigned mask)
{
cw_sig_eintr = 0x0008
};
+extern TIMER_BASIC_INFORMATION cw_nowait;
+
const unsigned cw_std_mask = cw_cancel | cw_cancel_self | cw_sig;
DWORD cancelable_wait (HANDLE, PLARGE_INTEGER timeout = NULL,
__attribute__ ((regparm (3)));
static inline DWORD __attribute__ ((always_inline))
-cygwait (HANDLE h, DWORD howlong = INFINITE)
+cancelable_wait (HANDLE h, DWORD howlong, unsigned mask)
{
PLARGE_INTEGER pli_howlong;
LARGE_INTEGER li_howlong;
li_howlong.QuadPart = 10000ULL * howlong;
pli_howlong = &li_howlong;
}
- return cancelable_wait (h, pli_howlong, cw_cancel | cw_sig_eintr);
+
+ return cancelable_wait (h, pi_howlong, mask);
+}
+
+static inline DWORD __attribute__ ((always_inline))
+cygwait (HANDLE h, DWORD howlong = INFINITE)
+{
+ return cancelable_wait (h, howlong, cw_cancel | cw_sig_eintr);
}
static inline DWORD __attribute__ ((always_inline))
{
return cygwait ((HANDLE) NULL, howlong);
}
+
+class set_thread_waiting
+{
+ void doit (bool setit, DWORD& here)
+ {
+ if (setit)
+ {
+ if (_my_tls.signal_arrived == NULL)
+ _my_tls.signal_arrived = CreateEvent (&sec_none_nih, false, false, NULL);
+ here = _my_tls.signal_arrived;
+ _my_tls.waiting = true;
+ }
+ }
+public:
+ set_thread_waiting (bool setit, DWORD& here) { doit (setit, here); }
+ set_thread_waiting (DWORD& here) { doit (true, here); }
+
+ ~set_thread_waiting ()
+ {
+ if (_my_tls.waiting)
+ {
+ _my_tls.waiting = false;
+ ResetEvent (_my_tls.signal_arrived);
+ }
+ }
+};
strace.microseconds ();
#endif
- create_signal_arrived (); /* FIXME: move into wait_sig? */
-
/* Initialize debug muto, if DLL is built with --enable-debugging.
Need to do this before any helper threads start. */
debug_init ();
sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask);
pthread_testcancel ();
- cancelable_wait (signal_arrived, NULL, cw_cancel | cw_cancel_self);
+ cancelable_wait (NULL, NULL, cw_cancel | cw_cancel_self | cw_sig_eintr);
set_sig_errno (EINTR); // Per POSIX
sigproc_printf ("process %d stopped by signal %d", myself->pid, sig);
HANDLE w4[2];
w4[0] = sigCONT;
- w4[1] = signal_arrived;
- switch (WaitForMultipleObjects (2, w4, TRUE, INFINITE))
+ switch (cancelable_wait (sigCONT, NULL, cw_sig_eintr))
{
case WAIT_OBJECT_0:
case WAIT_OBJECT_0 + 1:
{
sigproc_printf ("default signal %d ignored", si.si_signo);
if (continue_now)
- SetEvent (signal_arrived);
+ SetEvent (use_tls->signal_arrived);
goto done;
}
pthread_testcancel ();
/* Using IsEventSignalled like this is racy since another thread could
be waiting for signal_arrived. */
- if (IsEventSignalled (signal_arrived)
+ if (cancelable_wait (NULL, cw_nowait, cw_sig_eintr) == WAIT_SIGNALED
&& !_my_tls.call_signal_handler ())
{
set_errno (EINTR);
return SOCKET_ERROR;
}
- WSAEVENT ev[2] = { wsock_evt, signal_arrived };
+ WSAEVENT ev[2] = { wsock_evt };
+ set_thread_waiting (ev[1]);
switch (WSAWaitForMultipleEvents (2, ev, FALSE, 50, FALSE))
{
case WSA_WAIT_TIMEOUT:
res = -1;
break;
}
- if (WaitForSingleObject (signal_arrived, 10) == WAIT_OBJECT_0)
+ if (cygwait (10) == WAIT_SIGNALED)
{
set_errno (EINTR);
res = -1;
inline bool
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
cancelable. */
DWORD timeout = cancelable && is_nonblocking () ? 0 : INFINITE;
restart:
- switch (WaitForMultipleObjects (cnt, w4, FALSE, timeout))
+ switch (cancelable_wait (mt_mtx, timeout, cw_sig | cw_cancel | cw_cancel_self))
{
case WAIT_OBJECT_0:
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:
set_errno (EAGAIN);
return false;
{
/* Don't raise a SIGTT* signal if we have already been
interrupted by another signal. */
- if (WaitForSingleObject (signal_arrived, 0) != WAIT_OBJECT_0)
+ if (cygwait (0) != WAIT_SIGNALED)
{
siginfo_t si = {0};
si.si_signo = sig;
goto out;
}
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 ())
{
set_errno (EINTR);
return;
}
- HANDLE w4[3] = { get_handle (), signal_arrived, NULL };
+ HANDLE w4[3] = { get_handle (), };
+ set_thread_waiting (w4[1]);
DWORD cnt = 2;
if ((w4[cnt] = pthread::get_cancel_event ()) != NULL)
++cnt;
timeout = 100L;
DWORD WAIT_SIGNAL_ARRIVED = WAIT_OBJECT_0 + wait_count;
- w4[wait_count++] = signal_arrived;
+ set_thread_waiting (w4[wait_count++]);
DWORD WAIT_THREAD_CANCELED = WAIT_TIMEOUT + 1;
HANDLE cancel_event = pthread::get_cancel_event ();
static int
ipc_mutex_lock (HANDLE mtx)
{
- HANDLE h[2] = { mtx, signal_arrived };
-
- switch (WaitForMultipleObjects (2, h, FALSE, INFINITE))
+ switch (cancelable_wait (mtx, NULL, cw_sig_eintr | cw_cancel | cw_cancel_self))
{
case WAIT_OBJECT_0:
case WAIT_ABANDONED_0:
return 0;
- case WAIT_OBJECT_0 + 1:
+ case WAIT_SIGNALED:
set_errno (EINTR);
return 1;
default:
static int
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 timer_idx = 0;
int ret = 0;
+ set_thread_waiting (w4[1]);
if ((w4[cnt] = pthread::get_cancel_event ()) != NULL)
++cnt;
if (abstime)
select_record *s = &start;
DWORD m = 0;
- w4[m++] = signal_arrived; /* Always wait for the arrival of a signal. */
+ set_thread_waiting (w4[m++]);
if ((w4[m] = pthread::get_cancel_event ()) != NULL)
m++;
syscall_printf ("clock_nanosleep (%ld.%09ld)", rqtp->tv_sec, rqtp->tv_nsec);
- int rc = cancelable_wait (signal_arrived, &timeout);
- if (rc == WAIT_OBJECT_0)
- {
- _my_tls.call_signal_handler ();
- res = EINTR;
- }
+ int rc = cancelable_wait (NULL, &timeout, cw_sig | cw_cancel | cw_cancel_self);
+ if (rc == WAIT_SIGNALED)
+ res = EINTR;
/* according to POSIX, rmtp is used only if !abstime */
if (rmtp && !abstime)
sigwaitinfo (const sigset_t *set, siginfo_t *info)
{
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;
sig_dispatch_pending (true);
int res;
- switch (WaitForSingleObject (h, INFINITE))
+ switch (cancelable_wait (NULL, NULL, cw_sig | cw_cancel | cw_cancel_self))
{
- case WAIT_OBJECT_0:
+ case WAIT_SIGNALED:
if (!sigismember (set, _my_tls.infodata.si_signo))
{
set_errno (EINTR);
res = -1;
}
- _my_tls.event = NULL;
- CloseHandle (h);
sigproc_printf ("returning signal %d", res);
return res;
}
char NO_COPY myself_nowait_dummy[1] = {'0'};// Flag to sig_send that signal goes to
// 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
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.
This routine starts the signal handling thread. */
void __stdcall
int __stdcall process () __attribute__ ((regparm (1)));
};
-extern HANDLE signal_arrived;
extern HANDLE sigCONT;
void __stdcall sig_dispatch_pending (bool fast = false);
int __stdcall sig_send (_pinfo *, int) __attribute__ ((regparm (2)));
void __stdcall signal_fixup_after_exec ();
void __stdcall sigalloc ();
-void __stdcall create_signal_arrived ();
int kill_pgrp (pid_t, siginfo_t&);
int killsys (pid_t, int);
{
debug_printf ("status %p", status);
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
files and while doing that disallow DELETE access. That's really