patch-2.3.40 linux/kernel/signal.c
Next file: linux/lib/inflate.c
Previous file: linux/kernel/sched.c
Back to the patch index
Back to the overall index
- Lines: 237
- Date:
Thu Jan 20 10:48:35 2000
- Orig file:
v2.3.39/linux/kernel/signal.c
- Orig date:
Tue Jan 11 22:31:45 2000
diff -u --recursive --new-file v2.3.39/linux/kernel/signal.c linux/kernel/signal.c
@@ -132,56 +132,41 @@
int reset = 1;
/* Collect the siginfo appropriate to this signal. */
- if (sig < SIGRTMIN) {
- /* XXX: As an extension, support queueing exactly
- one non-rt signal if SA_SIGINFO is set, so that
- we can get more detailed information about the
- cause of the signal. */
- /* Deciding not to init these couple of fields is
- more expensive that just initializing them. */
+ struct signal_queue *q, **pp;
+ pp = ¤t->sigqueue;
+ q = current->sigqueue;
+
+ /* Find the one we're interested in ... */
+ for ( ; q ; pp = &q->next, q = q->next)
+ if (q->info.si_signo == sig)
+ break;
+ if (q) {
+ if ((*pp = q->next) == NULL)
+ current->sigqueue_tail = pp;
+ *info = q->info;
+ kmem_cache_free(signal_queue_cachep,q);
+ atomic_dec(&nr_queued_signals);
+
+ /* then see if this signal is still pending. */
+ q = *pp;
+ while (q) {
+ if (q->info.si_signo == sig) {
+ reset = 0;
+ break;
+ }
+ q = q->next;
+ }
+ } else {
+ /* Ok, it wasn't in the queue. It must have
+ been sent either by a non-rt mechanism and
+ we ran out of queue space. So zero out the
+ info. */
info->si_signo = sig;
info->si_errno = 0;
info->si_code = 0;
info->si_pid = 0;
info->si_uid = 0;
- SET_UID16(info->si_uid16, 0);
- } else {
- struct signal_queue *q, **pp;
- pp = ¤t->sigqueue;
- q = current->sigqueue;
-
- /* Find the one we're interested in ... */
- for ( ; q ; pp = &q->next, q = q->next)
- if (q->info.si_signo == sig)
- break;
- if (q) {
- if ((*pp = q->next) == NULL)
- current->sigqueue_tail = pp;
- *info = q->info;
- kmem_cache_free(signal_queue_cachep,q);
- atomic_dec(&nr_queued_signals);
-
- /* then see if this signal is still pending. */
- q = *pp;
- while (q) {
- if (q->info.si_signo == sig) {
- reset = 0;
- break;
- }
- q = q->next;
- }
- } else {
- /* Ok, it wasn't in the queue. It must have
- been sent either by a non-rt mechanism and
- we ran out of queue space. So zero out the
- info. */
- info->si_signo = sig;
- info->si_errno = 0;
- info->si_code = 0;
- info->si_pid = 0;
- info->si_uid = 0;
- SET_UID16(info->si_uid16, 0);
- }
+ SET_SIGINFO_UID16(info->si_uid16, 0);
}
if (reset)
@@ -255,6 +240,8 @@
{
unsigned long flags;
int ret;
+ struct signal_queue *q = 0;
+
#if DEBUG_SIG
printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
@@ -307,43 +294,38 @@
if (ignored_signal(sig, t))
goto out;
- if (sig < SIGRTMIN) {
- /* Non-real-time signals are not queued. */
- /* XXX: As an extension, support queueing exactly one
- non-rt signal if SA_SIGINFO is set, so that we can
- get more detailed information about the cause of
- the signal. */
- if (sigismember(&t->signal, sig))
- goto out;
- } else {
- /* Real-time signals must be queued if sent by sigqueue, or
- some other real-time mechanism. It is implementation
- defined whether kill() does so. We attempt to do so, on
- the principle of least surprise, but since kill is not
- allowed to fail with EAGAIN when low on memory we just
- make sure at least one signal gets delivered and don't
- pass on the info struct. */
-
- struct signal_queue *q = 0;
-
- if (atomic_read(&nr_queued_signals) < max_queued_signals) {
- q = (struct signal_queue *)
- kmem_cache_alloc(signal_queue_cachep, GFP_ATOMIC);
- }
-
- if (q) {
- atomic_inc(&nr_queued_signals);
- q->next = NULL;
- *t->sigqueue_tail = q;
- t->sigqueue_tail = &q->next;
- switch ((unsigned long) info) {
+ /* Support queueing exactly one non-rt signal, so that we
+ can get more detailed information about the cause of
+ the signal. */
+ if (sig < SIGRTMIN && sigismember(&t->signal, sig))
+ goto out;
+
+ /* Real-time signals must be queued if sent by sigqueue, or
+ some other real-time mechanism. It is implementation
+ defined whether kill() does so. We attempt to do so, on
+ the principle of least surprise, but since kill is not
+ allowed to fail with EAGAIN when low on memory we just
+ make sure at least one signal gets delivered and don't
+ pass on the info struct. */
+
+ if (atomic_read(&nr_queued_signals) < max_queued_signals) {
+ q = (struct signal_queue *)
+ kmem_cache_alloc(signal_queue_cachep, GFP_ATOMIC);
+ }
+
+ if (q) {
+ atomic_inc(&nr_queued_signals);
+ q->next = NULL;
+ *t->sigqueue_tail = q;
+ t->sigqueue_tail = &q->next;
+ switch ((unsigned long) info) {
case 0:
q->info.si_signo = sig;
q->info.si_errno = 0;
q->info.si_code = SI_USER;
q->info.si_pid = current->pid;
q->info.si_uid = current->uid;
- SET_UID16(q->info.si_uid16, current->uid);
+ SET_SIGINFO_UID16(q->info.si_uid16, current->uid);
break;
case 1:
q->info.si_signo = sig;
@@ -351,17 +333,16 @@
q->info.si_code = SI_KERNEL;
q->info.si_pid = 0;
q->info.si_uid = 0;
- SET_UID16(q->info.si_uid16, 0);
+ SET_SIGINFO_UID16(q->info.si_uid16, 0);
break;
default:
q->info = *info;
break;
- }
- } else {
- /* Queue overflow, we have to abort. */
- ret = -EAGAIN;
- goto out;
}
+ } else {
+ /* Queue overflow, we have to abort. */
+ ret = -EAGAIN;
+ goto out;
}
sigaddset(&t->signal, sig);
@@ -739,6 +720,7 @@
* Invert the set of allowed signals to get those we
* want to block.
*/
+ sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
signotset(&these);
if (uts) {
@@ -801,7 +783,7 @@
info.si_code = SI_USER;
info.si_pid = current->pid;
info.si_uid = current->uid;
- SET_UID16(info.si_uid16, current->uid);
+ SET_SIGINFO_UID16(info.si_uid16, current->uid);
return kill_something_info(sig, &info, pid);
}
@@ -875,7 +857,8 @@
if (q->info.si_signo != sig)
pp = &q->next;
else {
- *pp = q->next;
+ if ((*pp = q->next) == NULL)
+ current->sigqueue_tail = pp;
kmem_cache_free(signal_queue_cachep, q);
atomic_dec(&nr_queued_signals);
}
@@ -922,10 +905,18 @@
goto out;
error = -EINVAL;
- if (ss_flags & ~SS_DISABLE)
+ /*
+ *
+ * Note - this code used to test ss_flags incorrectly
+ * old code may have been written using ss_flags==0
+ * to mean ss_flags==SS_ONSTACK (as this was the only
+ * way that worked) - this fix preserves that older
+ * mechanism
+ */
+ if (ss_flags != SS_DISABLE && ss_flags != SS_ONSTACK && ss_flags != 0)
goto out;
- if (ss_flags & SS_DISABLE) {
+ if (ss_flags == SS_DISABLE) {
ss_size = 0;
ss_sp = NULL;
} else {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)