* exceptions.cc (setup_handler): Signal event for any sigwaitinfo if it exists
to force signal to be handled. Zero event here to prevent races. * signal.cc (sigwaitinfo): Use local handle value for everything since signal thread could zero event element at any time. Detect when awaking due to thread not in mask and set return value and errno accordingly. Don't set signal number to zero unless we've recognized the signal. * sigproc.cc (sigq): Rename from sigqueue throughout. * thread.cc (pthread::join): Handle signals received while waiting for thread to terminate. * cygwin.din: Export sighold, sigqueue. * exceptions.cc (sighold): Define new function. * signal.cc (handle_sigprocmask): Set correct errno for invalid signal. Simplify debugging output. (sigqueue): Define new function. * include/cygwin/signal.h (sighold): Declare new function. (sigqueue): Ditto. * include/cygwin/version.h: Bump API minor version number. * include/limits.h (TIMER_MAX): Define. (_POSIX_TIMER_MAX): Ditto.
This commit is contained in:
parent
f9e19c0931
commit
ca713cfab3
|
@ -1,3 +1,31 @@
|
|||
2004-02-25 Christopher Faylor <cgf@redhat.com>
|
||||
|
||||
* exceptions.cc (setup_handler): Signal event for any sigwaitinfo if it
|
||||
exists to force signal to be handled. Zero event here to prevent
|
||||
races.
|
||||
* signal.cc (sigwaitinfo): Use local handle value for everything since
|
||||
signal thread could zero event element at any time. Detect when
|
||||
awaking due to thread not in mask and set return value and errno
|
||||
accordingly. Don't set signal number to zero unless we've recognized
|
||||
the signal.
|
||||
* sigproc.cc (sigq): Rename from sigqueue throughout.
|
||||
|
||||
* thread.cc (pthread::join): Handle signals received while waiting for
|
||||
thread to terminate.
|
||||
|
||||
2004-02-25 Christopher Faylor <cgf@redhat.com>
|
||||
|
||||
* cygwin.din: Export sighold, sigqueue.
|
||||
* exceptions.cc (sighold): Define new function.
|
||||
* signal.cc (handle_sigprocmask): Set correct errno for invalid signal.
|
||||
Simplify debugging output.
|
||||
(sigqueue): Define new function.
|
||||
* include/cygwin/signal.h (sighold): Declare new function.
|
||||
(sigqueue): Ditto.
|
||||
* include/cygwin/version.h: Bump API minor version number.
|
||||
* include/limits.h (TIMER_MAX): Define.
|
||||
(_POSIX_TIMER_MAX): Ditto.
|
||||
|
||||
2004-02-25 Brian Ford <ford@vss.fsi.com>,
|
||||
Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
|
|
|
@ -1225,6 +1225,8 @@ sigaddset SIGFE
|
|||
sigdelset SIGFE
|
||||
sigemptyset NOSIGFE
|
||||
sigfillset NOSIGFE
|
||||
sighold SIGFE
|
||||
sigqueue SIGFE
|
||||
siginterrupt SIGFE
|
||||
sigismember SIGFE
|
||||
signal SIGFE
|
||||
|
|
|
@ -813,6 +813,12 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls)
|
|||
out:
|
||||
if (locked)
|
||||
tls->unlock ();
|
||||
if (interrupted && tls->event)
|
||||
{
|
||||
HANDLE h = tls->event;
|
||||
tls->event = NULL;
|
||||
SetEvent (h);
|
||||
}
|
||||
sigproc_printf ("signal %d %sdelivered", sig, interrupted ? "" : "not ");
|
||||
return interrupted;
|
||||
}
|
||||
|
@ -906,6 +912,24 @@ set_process_mask (sigset_t newmask)
|
|||
set_signal_mask (newmask);
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
sighold (int sig)
|
||||
{
|
||||
/* check that sig is in right range */
|
||||
if (sig < 0 || sig >= NSIG)
|
||||
{
|
||||
set_errno (EINVAL);
|
||||
syscall_printf ("signal %d out of range", sig);
|
||||
return -1;
|
||||
}
|
||||
mask_sync->acquire (INFINITE);
|
||||
sigset_t mask = myself->getsigmask ();
|
||||
sigaddset (&mask, sig);
|
||||
set_signal_mask (mask);
|
||||
mask_sync->release ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the signal mask for this process.
|
||||
Note that some signals are unmaskable, as in UNIX. */
|
||||
extern "C" void __stdcall
|
||||
|
|
|
@ -206,6 +206,8 @@ struct sigaction
|
|||
|
||||
int sigwait (const sigset_t *, int *);
|
||||
int sigwaitinfo (const sigset_t *, siginfo_t *);
|
||||
int sighold (int);
|
||||
int sigqueue(pid_t, int, const union sigval);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -236,12 +236,13 @@ details. */
|
|||
109: Oh well. Someone uses reent_data.
|
||||
110: Export clock_gettime, sigwaitinfo, timer_create, timer_delete,
|
||||
timer_settime
|
||||
111: Export sigqueue, sighold.
|
||||
*/
|
||||
|
||||
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
|
||||
|
||||
#define CYGWIN_VERSION_API_MAJOR 0
|
||||
#define CYGWIN_VERSION_API_MINOR 110
|
||||
#define CYGWIN_VERSION_API_MINOR 111
|
||||
|
||||
/* There is also a compatibity version number associated with the
|
||||
shared memory regions. It is incremented when incompatible
|
||||
|
|
|
@ -147,6 +147,10 @@ details. */
|
|||
#undef PIPE_BUF
|
||||
#define PIPE_BUF 4096
|
||||
|
||||
/* Maximum number of timer expiration overruns. */
|
||||
#undef TIMER_MAX
|
||||
#define TIMER_MAX 32
|
||||
|
||||
/* POSIX values */
|
||||
/* These should never vary from one system type to another */
|
||||
/* They represent the minimum values that POSIX systems must support.
|
||||
|
@ -165,6 +169,7 @@ details. */
|
|||
#define _POSIX_STREAM_MAX 8
|
||||
#define _POSIX_TZNAME_MAX 3
|
||||
#define _POSIX_RTSIG_MAX 8
|
||||
#define _POSIX_TIMER_MAX 32
|
||||
|
||||
#define RTSIG_MAX _POSIX_RTSIG_MAX
|
||||
|
||||
|
|
|
@ -141,8 +141,8 @@ handle_sigprocmask (int sig, const sigset_t *set, sigset_t *oldset, sigset_t& op
|
|||
/* check that sig is in right range */
|
||||
if (sig < 0 || sig >= NSIG)
|
||||
{
|
||||
set_errno (ESRCH);
|
||||
syscall_printf ("SIG_ERR = sigprocmask signal %d out of range", sig);
|
||||
set_errno (EINVAL);
|
||||
syscall_printf ("signal %d out of range", sig);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -493,30 +493,54 @@ sigwaitinfo (const sigset_t *set, siginfo_t *info)
|
|||
pthread_testcancel ();
|
||||
HANDLE h;
|
||||
h = _my_tls.event = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
|
||||
if (!_my_tls.event)
|
||||
if (!h)
|
||||
{
|
||||
__seterrno ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
_my_tls.sigwait_mask = *set;
|
||||
sig_dispatch_pending (true);
|
||||
|
||||
int res;
|
||||
switch (WaitForSingleObject (_my_tls.event, INFINITE))
|
||||
switch (WaitForSingleObject (h, INFINITE))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
res = _my_tls.infodata.si_signo;
|
||||
sigproc_printf ("returning sig %d", res);
|
||||
if (info)
|
||||
*info = _my_tls.infodata;
|
||||
if (!sigismember (set, _my_tls.infodata.si_signo))
|
||||
{
|
||||
set_errno (EINTR);
|
||||
res = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (info)
|
||||
*info = _my_tls.infodata;
|
||||
res = _my_tls.infodata.si_signo;
|
||||
InterlockedExchange ((LONG *) &_my_tls.sig, (LONG) 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
__seterrno ();
|
||||
res = -1;
|
||||
}
|
||||
_my_tls.event = NULL;
|
||||
InterlockedExchange ((LONG *) &_my_tls.sig, (LONG) 0);
|
||||
CloseHandle (h);
|
||||
sig_dispatch_pending ();
|
||||
sigproc_printf ("returning sig %d", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
sigqueue (pid_t pid, int sig, const union sigval value)
|
||||
{
|
||||
siginfo_t si;
|
||||
pinfo dest (pid);
|
||||
if (!dest)
|
||||
{
|
||||
set_errno (ESRCH);
|
||||
return -1;
|
||||
}
|
||||
si.si_signo = sig;
|
||||
si.si_code = SI_USER;
|
||||
si.si_pid = si.si_uid = si.si_errno = 0;
|
||||
si.si_value = value;
|
||||
return sig_send (dest, si);
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ public:
|
|||
friend void __stdcall sig_dispatch_pending (bool);
|
||||
};
|
||||
|
||||
static pending_signals sigqueue;
|
||||
static pending_signals sigq;
|
||||
|
||||
struct sigaction *global_sigs;
|
||||
|
||||
|
@ -537,15 +537,15 @@ sig_clear (int target_sig)
|
|||
else
|
||||
{
|
||||
sigpacket *q;
|
||||
sigpacket *save = sigqueue.save ();
|
||||
sigqueue.reset ();
|
||||
while ((q = sigqueue.next ()))
|
||||
sigpacket *save = sigq.save ();
|
||||
sigq.reset ();
|
||||
while ((q = sigq.next ()))
|
||||
if (q->si.si_signo == target_sig)
|
||||
{
|
||||
q->si.si_signo = __SIGDELETE;
|
||||
break;
|
||||
}
|
||||
sigqueue.restore (save);
|
||||
sigq.restore (save);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -564,11 +564,11 @@ sigpending (sigset_t *mask)
|
|||
void __stdcall
|
||||
sig_dispatch_pending (bool fast)
|
||||
{
|
||||
if (exit_state || GetCurrentThreadId () == sigtid || !sigqueue.start.next)
|
||||
if (exit_state || GetCurrentThreadId () == sigtid || !sigq.start.next)
|
||||
{
|
||||
#ifdef DEBUGGING
|
||||
sigproc_printf ("exit_state %d, cur thread id %p, sigtid %p, sigqueue.start.next %p",
|
||||
exit_state, GetCurrentThreadId (), sigtid, sigqueue.start.next);
|
||||
sigproc_printf ("exit_state %d, cur thread id %p, sigtid %p, sigq.start.next %p",
|
||||
exit_state, GetCurrentThreadId (), sigtid, sigq.start.next);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
@ -1156,17 +1156,17 @@ wait_sig (VOID *self)
|
|||
case __SIGPENDING:
|
||||
*pack.mask = 0;
|
||||
unsigned bit;
|
||||
sigqueue.reset ();
|
||||
while ((q = sigqueue.next ()))
|
||||
sigq.reset ();
|
||||
while ((q = sigq.next ()))
|
||||
if (myself->getsigmask () & (bit = SIGTOMASK (q->si.si_signo)))
|
||||
*pack.mask |= bit;
|
||||
break;
|
||||
case __SIGFLUSH:
|
||||
case __SIGFLUSHFAST:
|
||||
sigqueue.reset ();
|
||||
while ((q = sigqueue.next ()))
|
||||
sigq.reset ();
|
||||
while ((q = sigq.next ()))
|
||||
if (q->si.si_signo == __SIGDELETE || q->process () > 0)
|
||||
sigqueue.del ();
|
||||
sigq.del ();
|
||||
break;
|
||||
default:
|
||||
if (pack.si.si_signo < 0)
|
||||
|
@ -1181,7 +1181,7 @@ wait_sig (VOID *self)
|
|||
if (!sigres)
|
||||
system_printf ("Failed to arm signal %d from pid %d", pack.sig, pack.pid);
|
||||
#endif
|
||||
sigqueue.add (pack); // FIXME: Shouldn't add this in !sh condition
|
||||
sigq.add (pack); // FIXME: Shouldn't add this in !sh condition
|
||||
}
|
||||
if (sig == SIGCHLD)
|
||||
proc_subproc (PROC_CLEARWAIT, 0);
|
||||
|
|
|
@ -2181,24 +2181,31 @@ pthread::join (pthread_t *thread, void **return_val)
|
|||
(*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
|
||||
(*thread)->mutex.unlock ();
|
||||
|
||||
switch (cancelable_wait ((*thread)->win32_obj_id, INFINITE, false, false))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
if (return_val)
|
||||
*return_val = (*thread)->return_ptr;
|
||||
delete (*thread);
|
||||
break;
|
||||
case WAIT_CANCELED:
|
||||
// set joined thread back to joinable since we got canceled
|
||||
(*thread)->joiner = NULL;
|
||||
(*thread)->attr.joinable = PTHREAD_CREATE_JOINABLE;
|
||||
joiner->cancel_self ();
|
||||
// never reached
|
||||
break;
|
||||
default:
|
||||
// should never happen
|
||||
return EINVAL;
|
||||
}
|
||||
bool loop = false;
|
||||
do
|
||||
switch (cancelable_wait ((*thread)->win32_obj_id, INFINITE, false, true))
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
if (return_val)
|
||||
*return_val = (*thread)->return_ptr;
|
||||
delete (*thread);
|
||||
break;
|
||||
case WAIT_SIGNALED:
|
||||
_my_tls.call_signal_handler ();
|
||||
loop = true;
|
||||
break;
|
||||
case WAIT_CANCELED:
|
||||
// set joined thread back to joinable since we got canceled
|
||||
(*thread)->joiner = NULL;
|
||||
(*thread)->attr.joinable = PTHREAD_CREATE_JOINABLE;
|
||||
joiner->cancel_self ();
|
||||
// never reached
|
||||
break;
|
||||
default:
|
||||
// should never happen
|
||||
return EINVAL;
|
||||
}
|
||||
while (loop);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue