summaryrefslogtreecommitdiffstats
path: root/winsup
diff options
context:
space:
mode:
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog28
-rw-r--r--winsup/cygwin/cygwin.din2
-rw-r--r--winsup/cygwin/exceptions.cc24
-rw-r--r--winsup/cygwin/include/cygwin/signal.h2
-rw-r--r--winsup/cygwin/include/cygwin/version.h3
-rw-r--r--winsup/cygwin/include/limits.h5
-rw-r--r--winsup/cygwin/signal.cc46
-rw-r--r--winsup/cygwin/sigproc.cc28
-rw-r--r--winsup/cygwin/thread.cc43
9 files changed, 137 insertions, 44 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 08339465c..e0361ea60 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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>
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index 1a9e47a64..bb322360b 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -1225,6 +1225,8 @@ sigaddset SIGFE
sigdelset SIGFE
sigemptyset NOSIGFE
sigfillset NOSIGFE
+sighold SIGFE
+sigqueue SIGFE
siginterrupt SIGFE
sigismember SIGFE
signal SIGFE
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index f2aec7731..94163fd52 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -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
diff --git a/winsup/cygwin/include/cygwin/signal.h b/winsup/cygwin/include/cygwin/signal.h
index 864ddff7b..90d8df666 100644
--- a/winsup/cygwin/include/cygwin/signal.h
+++ b/winsup/cygwin/include/cygwin/signal.h
@@ -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
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index 7a5ee8881..a4d938427 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -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
diff --git a/winsup/cygwin/include/limits.h b/winsup/cygwin/include/limits.h
index 5d5244384..f32cf5340 100644
--- a/winsup/cygwin/include/limits.h
+++ b/winsup/cygwin/include/limits.h
@@ -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
diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc
index b0ac94a79..52c402c49 100644
--- a/winsup/cygwin/signal.cc
+++ b/winsup/cygwin/signal.cc
@@ -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);
+}
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index 993b0ec10..f3f04decc 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -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);
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index 7e102fed8..e119129d1 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -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;