Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog12
-rw-r--r--winsup/cygwin/include/cygwin/signal.h4
-rw-r--r--winsup/cygwin/signal.cc64
-rw-r--r--winsup/cygwin/sigproc.cc4
4 files changed, 63 insertions, 21 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index c1a7e084d..8ec6f3e1f 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,15 @@
+2006-03-23 Christopher Faylor <cgf@timesys.com>
+
+ * sigproc.cc (sigalloc): Don't set SA_RESTART here.
+ * signal.cc (_SA_NORESTART): New flag.
+ (sigaction_worker): New function, derived from sigaction. Don't set
+ internal flags unless called internally.
+ (sigaction): Use sigaction_worker.
+ (signal): Honor new _SA_NORESTART flag.
+ (siginterrupt): Set _SA_NORESTART flag appropriately. Use
+ sigaction_worker to set flags.
+ * include/cygwin/signal.h: Define _SA_INTERNAL_MASK here.
+
2006-03-22 Corinna Vinschen <corinna@vinschen.de>
* thread.cc (pthread_mutex::is_good_initializer_or_bad_object): Delete.
diff --git a/winsup/cygwin/include/cygwin/signal.h b/winsup/cygwin/include/cygwin/signal.h
index 0e0aab7d3..1061a7ab1 100644
--- a/winsup/cygwin/include/cygwin/signal.h
+++ b/winsup/cygwin/include/cygwin/signal.h
@@ -215,6 +215,10 @@ struct sigaction
#define SA_ONESHOT SA_RESETHAND /* Historical linux name */
#define SA_NOMASK SA_NODEFER /* Historical linux name */
+/* Used internally by cygwin. Included here to group everything in one place.
+ Do not use. */
+#define _SA_INTERNAL_MASK 0xf000 /* bits in this range are internal */
+
#define SIGHUP 1 /* hangup */
#define SIGINT 2 /* interrupt */
#define SIGQUIT 3 /* quit */
diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc
index 6a7edd914..bcaf6edb2 100644
--- a/winsup/cygwin/signal.cc
+++ b/winsup/cygwin/signal.cc
@@ -28,6 +28,11 @@ details. */
int sigcatchers; /* FIXME: Not thread safe. */
+#define _SA_NORESTART 0x8000
+
+static int sigaction_worker (int, const struct sigaction *, struct sigaction *, bool)
+ __attribute__ ((regparm (3)));
+
#define sigtrapped(func) ((func) != SIG_IGN && (func) != SIG_DFL)
static inline void
@@ -62,9 +67,16 @@ signal (int sig, _sig_func_ptr func)
}
prev = global_sigs[sig].sa_handler;
- global_sigs[sig].sa_handler = func;
- global_sigs[sig].sa_mask = 0;
- global_sigs[sig].sa_flags &= ~SA_SIGINFO;
+ struct sigaction& gs = global_sigs[sig];
+ if (gs.sa_flags & _SA_NORESTART)
+ gs.sa_flags &= ~SA_RESTART;
+ else
+ gs.sa_flags |= SA_RESTART;
+
+ gs.sa_mask = 0;
+ gs.sa_handler = func;
+ gs.sa_flags &= ~SA_SIGINFO;
+
set_sigcatchers (prev, func);
syscall_printf ("%p = signal (%d, %p)", prev, sig, func);
@@ -336,8 +348,8 @@ abort (void)
do_exit (SIGABRT); /* signal handler didn't exit. Goodbye. */
}
-extern "C" int
-sigaction (int sig, const struct sigaction *newact, struct sigaction *oldact)
+static int
+sigaction_worker (int sig, const struct sigaction *newact, struct sigaction *oldact, bool isinternal)
{
sig_dispatch_pending ();
/* check that sig is in right range */
@@ -361,30 +373,42 @@ sigaction (int sig, const struct sigaction *newact, struct sigaction *oldact)
set_errno (EINVAL);
return -1;
}
- struct sigaction& na = global_sigs[sig];
- na = *newact;
- if (!(na.sa_flags & SA_NODEFER))
- na.sa_mask |= SIGTOMASK(sig);
- if (na.sa_handler == SIG_IGN)
+ struct sigaction na = *newact;
+ struct sigaction& gs = global_sigs[sig];
+ if (!isinternal)
+ na.sa_flags &= ~_SA_INTERNAL_MASK;
+ gs = na;
+ if (!(gs.sa_flags & SA_NODEFER))
+ gs.sa_mask |= SIGTOMASK(sig);
+ if (gs.sa_handler == SIG_IGN)
sig_clear (sig);
- if (na.sa_handler == SIG_DFL && sig == SIGCHLD)
+ if (gs.sa_handler == SIG_DFL && sig == SIGCHLD)
sig_clear (sig);
- set_sigcatchers (oa.sa_handler, na.sa_handler);
+ set_sigcatchers (oa.sa_handler, gs.sa_handler);
if (sig == SIGCHLD)
{
myself->process_state &= ~PID_NOCLDSTOP;
- if (na.sa_flags & SA_NOCLDSTOP)
+ if (gs.sa_flags & SA_NOCLDSTOP)
myself->process_state |= PID_NOCLDSTOP;
}
}
if (oldact)
- *oldact = oa;
+ {
+ *oldact = oa;
+ oa.sa_flags &= ~_SA_INTERNAL_MASK;
+ }
return 0;
}
extern "C" int
+sigaction (int sig, const struct sigaction *newact, struct sigaction *oldact)
+{
+ return sigaction_worker (sig, newact, oldact, false);
+}
+
+extern "C" int
sigaddset (sigset_t *set, const int sig)
{
/* check that sig is in right range */
@@ -469,10 +493,16 @@ siginterrupt (int sig, int flag)
struct sigaction act;
sigaction (sig, NULL, &act);
if (flag)
- act.sa_flags &= ~SA_RESTART;
+ {
+ act.sa_flags &= ~SA_RESTART;
+ act.sa_flags |= _SA_NORESTART;
+ }
else
- act.sa_flags |= SA_RESTART;
- return sigaction (sig, &act, NULL);
+ {
+ act.sa_flags &= ~_SA_NORESTART;
+ act.sa_flags |= SA_RESTART;
+ }
+ return sigaction_worker (sig, &act, NULL, true);
}
extern "C" int
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index 0f927fe89..8de1ff8b9 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -115,10 +115,6 @@ sigalloc ()
cygheap->sigs = global_sigs =
(struct sigaction *) ccalloc (HEAP_SIGS, NSIG, sizeof (struct sigaction));
global_sigs[SIGSTOP].sa_flags = SA_RESTART | SA_NODEFER;
- for (int i = 0; i < NSIG; i++)
- /* SA_RESTART is set to maintain BSD compatible signal behaviour by default.
- This is also compatible with the behaviour of signal(2) in Linux. */
- global_sigs[i].sa_flags = SA_RESTART;
}
void __stdcall