2005-01-06 23:35:40 +00:00
|
|
|
/*-
|
2017-11-20 19:43:44 +00:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
*
|
1994-05-24 10:09:53 +00:00
|
|
|
* Copyright (c) 1982, 1986, 1989, 1991, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
* (c) UNIX System Laboratories, Inc.
|
|
|
|
* All or some portions of this file are derived from material licensed
|
|
|
|
* to the University of California by American Telephone and Telegraph
|
|
|
|
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
|
|
|
* the permission of UNIX System Laboratories, Inc.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2016-09-15 13:16:20 +00:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
1994-05-24 10:09:53 +00:00
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* @(#)kern_sig.c 8.7 (Berkeley) 4/18/94
|
|
|
|
*/
|
|
|
|
|
2003-06-11 00:56:59 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
1996-01-03 21:42:35 +00:00
|
|
|
#include "opt_ktrace.h"
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/param.h>
|
2015-02-10 04:34:39 +00:00
|
|
|
#include <sys/ctype.h>
|
2000-09-10 13:54:52 +00:00
|
|
|
#include <sys/systm.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/signalvar.h>
|
|
|
|
#include <sys/vnode.h>
|
|
|
|
#include <sys/acct.h>
|
2014-03-16 10:55:57 +00:00
|
|
|
#include <sys/capsicum.h>
|
2018-01-08 21:27:41 +00:00
|
|
|
#include <sys/compressor.h>
|
2001-01-16 01:00:43 +00:00
|
|
|
#include <sys/condvar.h>
|
2020-08-21 00:03:24 +00:00
|
|
|
#include <sys/devctl.h>
|
2003-05-05 21:26:25 +00:00
|
|
|
#include <sys/event.h>
|
|
|
|
#include <sys/fcntl.h>
|
2010-03-02 06:58:58 +00:00
|
|
|
#include <sys/imgact.h>
|
2003-05-05 21:26:25 +00:00
|
|
|
#include <sys/kernel.h>
|
2000-09-07 01:33:02 +00:00
|
|
|
#include <sys/ktr.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/ktrace.h>
|
2019-07-29 20:26:01 +00:00
|
|
|
#include <sys/limits.h>
|
2003-05-05 21:26:25 +00:00
|
|
|
#include <sys/lock.h>
|
|
|
|
#include <sys/malloc.h>
|
|
|
|
#include <sys/mutex.h>
|
2014-07-14 21:12:59 +00:00
|
|
|
#include <sys/refcount.h>
|
2003-05-05 21:26:25 +00:00
|
|
|
#include <sys/namei.h>
|
|
|
|
#include <sys/proc.h>
|
Add experimental support for process descriptors
A "process descriptor" file descriptor is used to manage processes
without using the PID namespace. This is required for Capsicum's
Capability Mode, where the PID namespace is unavailable.
New system calls pdfork(2) and pdkill(2) offer the functional equivalents
of fork(2) and kill(2). pdgetpid(2) allows querying the PID of the remote
process for debugging purposes. The currently-unimplemented pdwait(2) will,
in the future, allow querying rusage/exit status. In the interim, poll(2)
may be used to check (and wait for) process termination.
When a process is referenced by a process descriptor, it does not issue
SIGCHLD to the parent, making it suitable for use in libraries---a common
scenario when using library compartmentalisation from within large
applications (such as web browsers). Some observers may note a similarity
to Mach task ports; process descriptors provide a subset of this behaviour,
but in a UNIX style.
This feature is enabled by "options PROCDESC", but as with several other
Capsicum kernel features, is not enabled by default in GENERIC 9.0.
Reviewed by: jhb, kib
Approved by: re (kib), mentor (rwatson)
Sponsored by: Google Inc
2011-08-18 22:51:30 +00:00
|
|
|
#include <sys/procdesc.h>
|
2019-11-27 20:33:53 +00:00
|
|
|
#include <sys/ptrace.h>
|
2006-11-11 16:26:58 +00:00
|
|
|
#include <sys/posix4.h>
|
2011-05-26 18:54:07 +00:00
|
|
|
#include <sys/racct.h>
|
2001-03-28 08:41:04 +00:00
|
|
|
#include <sys/resourcevar.h>
|
2008-05-24 06:22:16 +00:00
|
|
|
#include <sys/sdt.h>
|
2008-03-08 16:31:29 +00:00
|
|
|
#include <sys/sbuf.h>
|
Switch the sleep/wakeup and condition variable implementations to use the
sleep queue interface:
- Sleep queues attempt to merge some of the benefits of both sleep queues
and condition variables. Having sleep qeueus in a hash table avoids
having to allocate a queue head for each wait channel. Thus, struct cv
has shrunk down to just a single char * pointer now. However, the
hash table does not hold threads directly, but queue heads. This means
that once you have located a queue in the hash bucket, you no longer have
to walk the rest of the hash chain looking for threads. Instead, you have
a list of all the threads sleeping on that wait channel.
- Outside of the sleepq code and the sleep/cv code the kernel no longer
differentiates between cv's and sleep/wakeup. For example, calls to
abortsleep() and cv_abort() are replaced with a call to sleepq_abort().
Thus, the TDF_CVWAITQ flag is removed. Also, calls to unsleep() and
cv_waitq_remove() have been replaced with calls to sleepq_remove().
- The sched_sleep() function no longer accepts a priority argument as
sleep's no longer inherently bump the priority. Instead, this is soley
a propery of msleep() which explicitly calls sched_prio() before
blocking.
- The TDF_ONSLEEPQ flag has been dropped as it was never used. The
associated TDF_SET_ONSLEEPQ and TDF_CLR_ON_SLEEPQ macros have also been
dropped and replaced with a single explicit clearing of td_wchan.
TD_SET_ONSLEEPQ() would really have only made sense if it had taken
the wait channel and message as arguments anyway. Now that that only
happens in one place, a macro would be overkill.
2004-02-27 18:52:44 +00:00
|
|
|
#include <sys/sleepqueue.h>
|
2001-04-27 19:28:25 +00:00
|
|
|
#include <sys/smp.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <sys/stat.h>
|
2001-03-28 11:52:56 +00:00
|
|
|
#include <sys/sx.h>
|
2002-09-01 20:37:28 +00:00
|
|
|
#include <sys/syscallsubr.h>
|
1998-06-28 08:37:45 +00:00
|
|
|
#include <sys/sysctl.h>
|
2003-05-05 21:26:25 +00:00
|
|
|
#include <sys/sysent.h>
|
|
|
|
#include <sys/syslog.h>
|
|
|
|
#include <sys/sysproto.h>
|
2005-10-30 02:56:08 +00:00
|
|
|
#include <sys/timers.h>
|
2001-09-08 20:02:33 +00:00
|
|
|
#include <sys/unistd.h>
|
2003-05-05 21:26:25 +00:00
|
|
|
#include <sys/wait.h>
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
#include <vm/vm.h>
|
|
|
|
#include <vm/vm_extern.h>
|
|
|
|
#include <vm/uma.h>
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2010-03-02 06:58:58 +00:00
|
|
|
#include <sys/jail.h>
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
#include <machine/cpu.h>
|
|
|
|
|
2006-02-14 01:17:03 +00:00
|
|
|
#include <security/audit/audit.h>
|
|
|
|
|
1999-10-12 13:14:18 +00:00
|
|
|
#define ONSIG 32 /* NSIG for osig* syscalls. XXX. */
|
|
|
|
|
2008-05-24 06:22:16 +00:00
|
|
|
SDT_PROVIDER_DECLARE(proc);
|
2015-12-16 23:39:27 +00:00
|
|
|
SDT_PROBE_DEFINE3(proc, , , signal__send,
|
|
|
|
"struct thread *", "struct proc *", "int");
|
|
|
|
SDT_PROBE_DEFINE2(proc, , , signal__clear,
|
|
|
|
"int", "ksiginfo_t *");
|
|
|
|
SDT_PROBE_DEFINE3(proc, , , signal__discard,
|
2013-08-15 04:08:55 +00:00
|
|
|
"struct thread *", "struct proc *", "int");
|
2008-05-24 06:22:16 +00:00
|
|
|
|
2002-07-03 06:15:26 +00:00
|
|
|
static int coredump(struct thread *);
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
static int killpg1(struct thread *td, int sig, int pgid, int all,
|
|
|
|
ksiginfo_t *ksi);
|
2013-03-18 17:23:58 +00:00
|
|
|
static int issignal(struct thread *td);
|
2020-03-10 20:04:38 +00:00
|
|
|
static void reschedule_signals(struct proc *p, sigset_t block, int flags);
|
2002-07-03 06:15:26 +00:00
|
|
|
static int sigprop(int sig);
|
Fix a long standing race between sleep queue and thread
suspension code. When a thread A is going to sleep, it calls
sleepq_catch_signals() to detect any pending signals or thread
suspension request, if nothing happens, it returns without
holding process lock or scheduler lock, this opens a race
window which allows thread B to come in and do process
suspension work, however since A is still at running state,
thread B can do nothing to A, thread A continues, and puts
itself into actually sleeping state, but B has never seen it,
and it sits there forever until B is woken up by other threads
sometimes later(this can be very long delay or never
happen). Fix this bug by forcing sleepq_catch_signals to
return with scheduler lock held.
Fix sleepq_abort() by passing it an interrupted code, previously,
it worked as wakeup_one(), and the interruption can not be
identified correctly by sleep queue code when the sleeping
thread is resumed.
Let thread_suspend_check() returns EINTR or ERESTART, so sleep
queue no longer has to use SIGSTOP as a hack to build a return
value.
Reviewed by: jhb
MFC after: 1 week
2006-02-15 23:52:01 +00:00
|
|
|
static void tdsigwakeup(struct thread *, int, sig_t, int);
|
2016-06-28 16:41:50 +00:00
|
|
|
static int sig_suspend_threads(struct thread *, struct proc *, int);
|
2000-04-16 18:53:38 +00:00
|
|
|
static int filt_sigattach(struct knote *kn);
|
|
|
|
static void filt_sigdetach(struct knote *kn);
|
|
|
|
static int filt_signal(struct knote *kn, long hint);
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
static struct thread *sigtd(struct proc *p, int sig, bool fast_sigblock);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
static void sigqueue_start(void);
|
|
|
|
|
|
|
|
static uma_zone_t ksiginfo_zone = NULL;
|
2009-09-12 20:03:45 +00:00
|
|
|
struct filterops sig_filtops = {
|
|
|
|
.f_isfd = 0,
|
|
|
|
.f_attach = filt_sigattach,
|
|
|
|
.f_detach = filt_sigdetach,
|
|
|
|
.f_event = filt_signal,
|
|
|
|
};
|
2000-04-16 18:53:38 +00:00
|
|
|
|
2010-07-08 19:15:26 +00:00
|
|
|
static int kern_logsigexit = 1;
|
2012-11-27 10:11:54 +00:00
|
|
|
SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW,
|
|
|
|
&kern_logsigexit, 0,
|
1999-05-03 23:57:32 +00:00
|
|
|
"Log processes quitting on abnormal signals to syslog(3)");
|
1998-07-28 22:34:12 +00:00
|
|
|
|
2005-12-09 08:29:29 +00:00
|
|
|
static int kern_forcesigexit = 1;
|
|
|
|
SYSCTL_INT(_kern, OID_AUTO, forcesigexit, CTLFLAG_RW,
|
|
|
|
&kern_forcesigexit, 0, "Force trap signal to be handled");
|
|
|
|
|
2020-02-26 14:26:36 +00:00
|
|
|
static SYSCTL_NODE(_kern, OID_AUTO, sigqueue, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
|
2011-11-07 15:43:11 +00:00
|
|
|
"POSIX real time signal");
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
|
|
|
|
static int max_pending_per_proc = 128;
|
|
|
|
SYSCTL_INT(_kern_sigqueue, OID_AUTO, max_pending_per_proc, CTLFLAG_RW,
|
|
|
|
&max_pending_per_proc, 0, "Max pending signals per proc");
|
|
|
|
|
|
|
|
static int preallocate_siginfo = 1024;
|
2014-06-28 03:56:17 +00:00
|
|
|
SYSCTL_INT(_kern_sigqueue, OID_AUTO, preallocate, CTLFLAG_RDTUN,
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
&preallocate_siginfo, 0, "Preallocated signal memory size");
|
|
|
|
|
|
|
|
static int signal_overflow = 0;
|
2005-12-09 02:26:44 +00:00
|
|
|
SYSCTL_INT(_kern_sigqueue, OID_AUTO, overflow, CTLFLAG_RD,
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
&signal_overflow, 0, "Number of signals overflew");
|
|
|
|
|
|
|
|
static int signal_alloc_fail = 0;
|
2005-12-09 02:26:44 +00:00
|
|
|
SYSCTL_INT(_kern_sigqueue, OID_AUTO, alloc_fail, CTLFLAG_RD,
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
&signal_alloc_fail, 0, "signals failed to be allocated");
|
|
|
|
|
2017-06-12 21:11:11 +00:00
|
|
|
static int kern_lognosys = 0;
|
|
|
|
SYSCTL_INT(_kern, OID_AUTO, lognosys, CTLFLAG_RWTUN, &kern_lognosys, 0,
|
|
|
|
"Log invalid syscalls");
|
|
|
|
|
2020-02-20 15:34:02 +00:00
|
|
|
__read_frequently bool sigfastblock_fetch_always = false;
|
|
|
|
SYSCTL_BOOL(_kern, OID_AUTO, sigfastblock_fetch_always, CTLFLAG_RWTUN,
|
|
|
|
&sigfastblock_fetch_always, 0,
|
|
|
|
"Fetch sigfastblock word on each syscall entry for proper "
|
|
|
|
"blocking semantic");
|
|
|
|
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
SYSINIT(signal, SI_SUB_P1003_1B, SI_ORDER_FIRST+3, sigqueue_start, NULL);
|
|
|
|
|
2002-01-10 01:25:35 +00:00
|
|
|
/*
|
|
|
|
* Policy -- Can ucred cr1 send SIGIO to process cr2?
|
|
|
|
* Should use cr_cansignal() once cr_cansignal() allows SIGIO and SIGURG
|
|
|
|
* in the right situations.
|
|
|
|
*/
|
|
|
|
#define CANSIGIO(cr1, cr2) \
|
|
|
|
((cr1)->cr_uid == 0 || \
|
|
|
|
(cr1)->cr_ruid == (cr2)->cr_ruid || \
|
|
|
|
(cr1)->cr_uid == (cr2)->cr_ruid || \
|
|
|
|
(cr1)->cr_ruid == (cr2)->cr_uid || \
|
|
|
|
(cr1)->cr_uid == (cr2)->cr_uid)
|
|
|
|
|
2010-07-08 19:15:26 +00:00
|
|
|
static int sugid_coredump;
|
2014-06-28 03:56:17 +00:00
|
|
|
SYSCTL_INT(_kern, OID_AUTO, sugid_coredump, CTLFLAG_RWTUN,
|
2009-10-12 15:49:48 +00:00
|
|
|
&sugid_coredump, 0, "Allow setuid and setgid processes to dump core");
|
1998-06-28 08:37:45 +00:00
|
|
|
|
2012-11-27 10:38:11 +00:00
|
|
|
static int capmode_coredump;
|
2014-06-28 03:56:17 +00:00
|
|
|
SYSCTL_INT(_kern, OID_AUTO, capmode_coredump, CTLFLAG_RWTUN,
|
2012-11-27 10:38:11 +00:00
|
|
|
&capmode_coredump, 0, "Allow processes in capability mode to dump core");
|
|
|
|
|
2000-03-21 07:10:42 +00:00
|
|
|
static int do_coredump = 1;
|
|
|
|
SYSCTL_INT(_kern, OID_AUTO, coredump, CTLFLAG_RW,
|
|
|
|
&do_coredump, 0, "Enable/Disable coredumps");
|
|
|
|
|
2004-08-09 05:46:46 +00:00
|
|
|
static int set_core_nodump_flag = 0;
|
|
|
|
SYSCTL_INT(_kern, OID_AUTO, nodump_coredump, CTLFLAG_RW, &set_core_nodump_flag,
|
|
|
|
0, "Enable setting the NODUMP flag on coredump files");
|
|
|
|
|
2015-03-24 02:17:17 +00:00
|
|
|
static int coredump_devctl = 0;
|
2015-02-10 04:34:39 +00:00
|
|
|
SYSCTL_INT(_kern, OID_AUTO, coredump_devctl, CTLFLAG_RW, &coredump_devctl,
|
|
|
|
0, "Generate a devctl notification when processes coredump");
|
|
|
|
|
1999-09-29 15:03:48 +00:00
|
|
|
/*
|
|
|
|
* Signal properties and actions.
|
|
|
|
* The array below categorizes the signals and their default actions
|
|
|
|
* according to the following properties:
|
|
|
|
*/
|
2016-09-02 18:22:56 +00:00
|
|
|
#define SIGPROP_KILL 0x01 /* terminates process by default */
|
|
|
|
#define SIGPROP_CORE 0x02 /* ditto and coredumps */
|
|
|
|
#define SIGPROP_STOP 0x04 /* suspend process */
|
|
|
|
#define SIGPROP_TTYSTOP 0x08 /* ditto, from tty */
|
|
|
|
#define SIGPROP_IGNORE 0x10 /* ignore by default */
|
|
|
|
#define SIGPROP_CONT 0x20 /* continue if suspended */
|
|
|
|
#define SIGPROP_CANTMASK 0x40 /* non-maskable, catchable */
|
1999-09-29 15:03:48 +00:00
|
|
|
|
|
|
|
static int sigproptbl[NSIG] = {
|
2016-09-06 22:03:53 +00:00
|
|
|
[SIGHUP] = SIGPROP_KILL,
|
|
|
|
[SIGINT] = SIGPROP_KILL,
|
|
|
|
[SIGQUIT] = SIGPROP_KILL | SIGPROP_CORE,
|
|
|
|
[SIGILL] = SIGPROP_KILL | SIGPROP_CORE,
|
|
|
|
[SIGTRAP] = SIGPROP_KILL | SIGPROP_CORE,
|
|
|
|
[SIGABRT] = SIGPROP_KILL | SIGPROP_CORE,
|
|
|
|
[SIGEMT] = SIGPROP_KILL | SIGPROP_CORE,
|
|
|
|
[SIGFPE] = SIGPROP_KILL | SIGPROP_CORE,
|
|
|
|
[SIGKILL] = SIGPROP_KILL,
|
|
|
|
[SIGBUS] = SIGPROP_KILL | SIGPROP_CORE,
|
|
|
|
[SIGSEGV] = SIGPROP_KILL | SIGPROP_CORE,
|
|
|
|
[SIGSYS] = SIGPROP_KILL | SIGPROP_CORE,
|
|
|
|
[SIGPIPE] = SIGPROP_KILL,
|
|
|
|
[SIGALRM] = SIGPROP_KILL,
|
|
|
|
[SIGTERM] = SIGPROP_KILL,
|
|
|
|
[SIGURG] = SIGPROP_IGNORE,
|
|
|
|
[SIGSTOP] = SIGPROP_STOP,
|
|
|
|
[SIGTSTP] = SIGPROP_STOP | SIGPROP_TTYSTOP,
|
|
|
|
[SIGCONT] = SIGPROP_IGNORE | SIGPROP_CONT,
|
|
|
|
[SIGCHLD] = SIGPROP_IGNORE,
|
|
|
|
[SIGTTIN] = SIGPROP_STOP | SIGPROP_TTYSTOP,
|
|
|
|
[SIGTTOU] = SIGPROP_STOP | SIGPROP_TTYSTOP,
|
|
|
|
[SIGIO] = SIGPROP_IGNORE,
|
|
|
|
[SIGXCPU] = SIGPROP_KILL,
|
|
|
|
[SIGXFSZ] = SIGPROP_KILL,
|
|
|
|
[SIGVTALRM] = SIGPROP_KILL,
|
|
|
|
[SIGPROF] = SIGPROP_KILL,
|
|
|
|
[SIGWINCH] = SIGPROP_IGNORE,
|
|
|
|
[SIGINFO] = SIGPROP_IGNORE,
|
|
|
|
[SIGUSR1] = SIGPROP_KILL,
|
|
|
|
[SIGUSR2] = SIGPROP_KILL,
|
1999-09-29 15:03:48 +00:00
|
|
|
};
|
|
|
|
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
sigset_t fastblock_mask;
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
static void
|
|
|
|
sigqueue_start(void)
|
|
|
|
{
|
|
|
|
ksiginfo_zone = uma_zcreate("ksiginfo", sizeof(ksiginfo_t),
|
|
|
|
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
|
|
|
|
uma_prealloc(ksiginfo_zone, preallocate_siginfo);
|
2005-12-01 00:25:50 +00:00
|
|
|
p31b_setcfg(CTL_P1003_1B_REALTIME_SIGNALS, _POSIX_REALTIME_SIGNALS);
|
|
|
|
p31b_setcfg(CTL_P1003_1B_RTSIG_MAX, SIGRTMAX - SIGRTMIN + 1);
|
|
|
|
p31b_setcfg(CTL_P1003_1B_SIGQUEUE_MAX, max_pending_per_proc);
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
SIGFILLSET(fastblock_mask);
|
|
|
|
SIG_CANTMASK(fastblock_mask);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
}
|
|
|
|
|
2005-10-23 04:12:26 +00:00
|
|
|
ksiginfo_t *
|
2005-11-08 09:09:26 +00:00
|
|
|
ksiginfo_alloc(int wait)
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
{
|
2005-11-08 09:09:26 +00:00
|
|
|
int flags;
|
|
|
|
|
|
|
|
flags = M_ZERO;
|
|
|
|
if (! wait)
|
|
|
|
flags |= M_NOWAIT;
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
if (ksiginfo_zone != NULL)
|
2005-11-08 09:09:26 +00:00
|
|
|
return ((ksiginfo_t *)uma_zalloc(ksiginfo_zone, flags));
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
2005-10-23 04:12:26 +00:00
|
|
|
void
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
ksiginfo_free(ksiginfo_t *ksi)
|
|
|
|
{
|
|
|
|
uma_zfree(ksiginfo_zone, ksi);
|
|
|
|
}
|
|
|
|
|
2005-10-23 04:12:26 +00:00
|
|
|
static __inline int
|
|
|
|
ksiginfo_tryfree(ksiginfo_t *ksi)
|
|
|
|
{
|
|
|
|
if (!(ksi->ksi_flags & KSI_EXT)) {
|
|
|
|
uma_zfree(ksiginfo_zone, ksi);
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
void
|
|
|
|
sigqueue_init(sigqueue_t *list, struct proc *p)
|
|
|
|
{
|
|
|
|
SIGEMPTYSET(list->sq_signals);
|
2006-03-02 14:06:40 +00:00
|
|
|
SIGEMPTYSET(list->sq_kill);
|
2017-02-20 15:53:16 +00:00
|
|
|
SIGEMPTYSET(list->sq_ptrace);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
TAILQ_INIT(&list->sq_list);
|
|
|
|
list->sq_proc = p;
|
|
|
|
list->sq_flags = SQ_INIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get a signal's ksiginfo.
|
|
|
|
* Return:
|
2012-11-27 10:11:54 +00:00
|
|
|
* 0 - signal not found
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
* others - signal number
|
2012-11-27 10:11:54 +00:00
|
|
|
*/
|
2010-01-23 11:43:30 +00:00
|
|
|
static int
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sigqueue_get(sigqueue_t *sq, int signo, ksiginfo_t *si)
|
|
|
|
{
|
|
|
|
struct proc *p = sq->sq_proc;
|
|
|
|
struct ksiginfo *ksi, *next;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
KASSERT(sq->sq_flags & SQ_INIT, ("sigqueue not inited"));
|
|
|
|
|
|
|
|
if (!SIGISMEMBER(sq->sq_signals, signo))
|
|
|
|
return (0);
|
|
|
|
|
2017-02-20 15:53:16 +00:00
|
|
|
if (SIGISMEMBER(sq->sq_ptrace, signo)) {
|
|
|
|
count++;
|
|
|
|
SIGDELSET(sq->sq_ptrace, signo);
|
|
|
|
si->ksi_flags |= KSI_PTRACE;
|
|
|
|
}
|
2006-03-02 14:06:40 +00:00
|
|
|
if (SIGISMEMBER(sq->sq_kill, signo)) {
|
|
|
|
count++;
|
2017-02-20 15:53:16 +00:00
|
|
|
if (count == 1)
|
|
|
|
SIGDELSET(sq->sq_kill, signo);
|
2006-03-02 14:06:40 +00:00
|
|
|
}
|
|
|
|
|
2006-10-22 00:09:41 +00:00
|
|
|
TAILQ_FOREACH_SAFE(ksi, &sq->sq_list, ksi_link, next) {
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
if (ksi->ksi_signo == signo) {
|
|
|
|
if (count == 0) {
|
|
|
|
TAILQ_REMOVE(&sq->sq_list, ksi, ksi_link);
|
2005-10-23 04:12:26 +00:00
|
|
|
ksi->ksi_sigq = NULL;
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
ksiginfo_copy(ksi, si);
|
2005-10-23 04:12:26 +00:00
|
|
|
if (ksiginfo_tryfree(ksi) && p != NULL)
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
p->p_pendingcnt--;
|
|
|
|
}
|
2006-12-25 03:00:15 +00:00
|
|
|
if (++count > 1)
|
|
|
|
break;
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count <= 1)
|
|
|
|
SIGDELSET(sq->sq_signals, signo);
|
|
|
|
si->ksi_signo = signo;
|
|
|
|
return (signo);
|
|
|
|
}
|
|
|
|
|
2005-10-23 04:12:26 +00:00
|
|
|
void
|
|
|
|
sigqueue_take(ksiginfo_t *ksi)
|
|
|
|
{
|
|
|
|
struct ksiginfo *kp;
|
|
|
|
struct proc *p;
|
|
|
|
sigqueue_t *sq;
|
|
|
|
|
2005-11-08 09:09:26 +00:00
|
|
|
if (ksi == NULL || (sq = ksi->ksi_sigq) == NULL)
|
2005-10-23 04:12:26 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
p = sq->sq_proc;
|
|
|
|
TAILQ_REMOVE(&sq->sq_list, ksi, ksi_link);
|
|
|
|
ksi->ksi_sigq = NULL;
|
|
|
|
if (!(ksi->ksi_flags & KSI_EXT) && p != NULL)
|
|
|
|
p->p_pendingcnt--;
|
|
|
|
|
|
|
|
for (kp = TAILQ_FIRST(&sq->sq_list); kp != NULL;
|
|
|
|
kp = TAILQ_NEXT(kp, ksi_link)) {
|
|
|
|
if (kp->ksi_signo == ksi->ksi_signo)
|
|
|
|
break;
|
|
|
|
}
|
2017-02-20 15:53:16 +00:00
|
|
|
if (kp == NULL && !SIGISMEMBER(sq->sq_kill, ksi->ksi_signo) &&
|
|
|
|
!SIGISMEMBER(sq->sq_ptrace, ksi->ksi_signo))
|
2005-10-23 04:12:26 +00:00
|
|
|
SIGDELSET(sq->sq_signals, ksi->ksi_signo);
|
|
|
|
}
|
|
|
|
|
2010-01-23 11:43:30 +00:00
|
|
|
static int
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sigqueue_add(sigqueue_t *sq, int signo, ksiginfo_t *si)
|
|
|
|
{
|
|
|
|
struct proc *p = sq->sq_proc;
|
|
|
|
struct ksiginfo *ksi;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
KASSERT(sq->sq_flags & SQ_INIT, ("sigqueue not inited"));
|
2012-11-27 10:11:54 +00:00
|
|
|
|
2017-02-20 15:53:16 +00:00
|
|
|
/*
|
|
|
|
* SIGKILL/SIGSTOP cannot be caught or masked, so take the fast path
|
|
|
|
* for these signals.
|
|
|
|
*/
|
2006-03-02 14:06:40 +00:00
|
|
|
if (signo == SIGKILL || signo == SIGSTOP || si == NULL) {
|
|
|
|
SIGADDSET(sq->sq_kill, signo);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
goto out_set_bit;
|
2006-03-02 14:06:40 +00:00
|
|
|
}
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
|
2005-10-23 04:12:26 +00:00
|
|
|
/* directly insert the ksi, don't copy it */
|
|
|
|
if (si->ksi_flags & KSI_INS) {
|
When traced process is about to receive the signal, the process is
stopped and debugger may modify or drop the signal. After the changes to
keep process-targeted signals on the process sigqueue, another thread
may note the old signal on the queue and act before the thread removes
changed or dropped signal from the process queue. Since process is
traced, it usually gets stopped. Or, if the same signal is delivered
while process was stopped, the thread may erronously remove it,
intending to remove the original signal.
Remove the signal from the queue before notifying the debugger. Restore
the siginfo to the head of sigqueue when signal is allowed to be
delivered to the debugee, using newly introduced KSI_HEAD ksiginfo_t
flag. This preserves required order of delivery. Always restore the
unchanged signal on the curthread sigqueue, not to the process queue,
since the thread is about to get it anyway, because sigmask cannot be
changed.
Handle failure of reinserting the siginfo into the queue by falling
back to sq_kill method, calling sigqueue_add with NULL ksi.
If debugger changed the signal to be delivered, use sigqueue_add()
with NULL ksi instead of only setting sq_signals bit.
Reported by: Gardner Bell <gbell72 rogers com>
Analyzed and first version of fix by: Tijl Coosemans <tijl coosemans org>
PR: 142757
Reviewed by: davidxu
MFC after: 2 weeks
2010-01-20 11:58:04 +00:00
|
|
|
if (si->ksi_flags & KSI_HEAD)
|
|
|
|
TAILQ_INSERT_HEAD(&sq->sq_list, si, ksi_link);
|
|
|
|
else
|
|
|
|
TAILQ_INSERT_TAIL(&sq->sq_list, si, ksi_link);
|
2005-10-23 04:12:26 +00:00
|
|
|
si->ksi_sigq = sq;
|
|
|
|
goto out_set_bit;
|
|
|
|
}
|
|
|
|
|
2006-03-02 14:06:40 +00:00
|
|
|
if (__predict_false(ksiginfo_zone == NULL)) {
|
|
|
|
SIGADDSET(sq->sq_kill, signo);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
goto out_set_bit;
|
2006-03-02 14:06:40 +00:00
|
|
|
}
|
2012-11-27 10:11:54 +00:00
|
|
|
|
2005-11-08 09:09:26 +00:00
|
|
|
if (p != NULL && p->p_pendingcnt >= max_pending_per_proc) {
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
signal_overflow++;
|
|
|
|
ret = EAGAIN;
|
2005-11-08 09:09:26 +00:00
|
|
|
} else if ((ksi = ksiginfo_alloc(0)) == NULL) {
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
signal_alloc_fail++;
|
|
|
|
ret = EAGAIN;
|
|
|
|
} else {
|
|
|
|
if (p != NULL)
|
|
|
|
p->p_pendingcnt++;
|
|
|
|
ksiginfo_copy(si, ksi);
|
|
|
|
ksi->ksi_signo = signo;
|
When traced process is about to receive the signal, the process is
stopped and debugger may modify or drop the signal. After the changes to
keep process-targeted signals on the process sigqueue, another thread
may note the old signal on the queue and act before the thread removes
changed or dropped signal from the process queue. Since process is
traced, it usually gets stopped. Or, if the same signal is delivered
while process was stopped, the thread may erronously remove it,
intending to remove the original signal.
Remove the signal from the queue before notifying the debugger. Restore
the siginfo to the head of sigqueue when signal is allowed to be
delivered to the debugee, using newly introduced KSI_HEAD ksiginfo_t
flag. This preserves required order of delivery. Always restore the
unchanged signal on the curthread sigqueue, not to the process queue,
since the thread is about to get it anyway, because sigmask cannot be
changed.
Handle failure of reinserting the siginfo into the queue by falling
back to sq_kill method, calling sigqueue_add with NULL ksi.
If debugger changed the signal to be delivered, use sigqueue_add()
with NULL ksi instead of only setting sq_signals bit.
Reported by: Gardner Bell <gbell72 rogers com>
Analyzed and first version of fix by: Tijl Coosemans <tijl coosemans org>
PR: 142757
Reviewed by: davidxu
MFC after: 2 weeks
2010-01-20 11:58:04 +00:00
|
|
|
if (si->ksi_flags & KSI_HEAD)
|
|
|
|
TAILQ_INSERT_HEAD(&sq->sq_list, ksi, ksi_link);
|
|
|
|
else
|
|
|
|
TAILQ_INSERT_TAIL(&sq->sq_list, ksi, ksi_link);
|
2005-10-23 04:12:26 +00:00
|
|
|
ksi->ksi_sigq = sq;
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
}
|
|
|
|
|
2017-02-20 15:53:16 +00:00
|
|
|
if (ret != 0) {
|
|
|
|
if ((si->ksi_flags & KSI_PTRACE) != 0) {
|
|
|
|
SIGADDSET(sq->sq_ptrace, signo);
|
|
|
|
ret = 0;
|
|
|
|
goto out_set_bit;
|
|
|
|
} else if ((si->ksi_flags & KSI_TRAP) != 0 ||
|
|
|
|
(si->ksi_flags & KSI_SIGQ) == 0) {
|
2006-03-02 14:06:40 +00:00
|
|
|
SIGADDSET(sq->sq_kill, signo);
|
2017-02-20 15:53:16 +00:00
|
|
|
ret = 0;
|
|
|
|
goto out_set_bit;
|
|
|
|
}
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
return (ret);
|
2017-02-20 15:53:16 +00:00
|
|
|
}
|
2012-11-27 10:11:54 +00:00
|
|
|
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
out_set_bit:
|
|
|
|
SIGADDSET(sq->sq_signals, signo);
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
sigqueue_flush(sigqueue_t *sq)
|
|
|
|
{
|
|
|
|
struct proc *p = sq->sq_proc;
|
|
|
|
ksiginfo_t *ksi;
|
|
|
|
|
|
|
|
KASSERT(sq->sq_flags & SQ_INIT, ("sigqueue not inited"));
|
|
|
|
|
2005-10-23 04:12:26 +00:00
|
|
|
if (p != NULL)
|
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
|
|
|
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
while ((ksi = TAILQ_FIRST(&sq->sq_list)) != NULL) {
|
|
|
|
TAILQ_REMOVE(&sq->sq_list, ksi, ksi_link);
|
2005-10-23 04:12:26 +00:00
|
|
|
ksi->ksi_sigq = NULL;
|
|
|
|
if (ksiginfo_tryfree(ksi) && p != NULL)
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
p->p_pendingcnt--;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGEMPTYSET(sq->sq_signals);
|
2006-03-02 14:06:40 +00:00
|
|
|
SIGEMPTYSET(sq->sq_kill);
|
2017-02-20 15:53:16 +00:00
|
|
|
SIGEMPTYSET(sq->sq_ptrace);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
}
|
|
|
|
|
2010-01-23 11:43:30 +00:00
|
|
|
static void
|
2010-10-13 06:28:40 +00:00
|
|
|
sigqueue_move_set(sigqueue_t *src, sigqueue_t *dst, const sigset_t *set)
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
{
|
2010-10-13 06:28:40 +00:00
|
|
|
sigset_t tmp;
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
struct proc *p1, *p2;
|
|
|
|
ksiginfo_t *ksi, *next;
|
|
|
|
|
|
|
|
KASSERT(src->sq_flags & SQ_INIT, ("src sigqueue not inited"));
|
|
|
|
KASSERT(dst->sq_flags & SQ_INIT, ("dst sigqueue not inited"));
|
|
|
|
p1 = src->sq_proc;
|
|
|
|
p2 = dst->sq_proc;
|
|
|
|
/* Move siginfo to target list */
|
2006-10-22 00:09:41 +00:00
|
|
|
TAILQ_FOREACH_SAFE(ksi, &src->sq_list, ksi_link, next) {
|
2010-10-13 06:28:40 +00:00
|
|
|
if (SIGISMEMBER(*set, ksi->ksi_signo)) {
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
TAILQ_REMOVE(&src->sq_list, ksi, ksi_link);
|
|
|
|
if (p1 != NULL)
|
|
|
|
p1->p_pendingcnt--;
|
|
|
|
TAILQ_INSERT_TAIL(&dst->sq_list, ksi, ksi_link);
|
2005-10-23 04:12:26 +00:00
|
|
|
ksi->ksi_sigq = dst;
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
if (p2 != NULL)
|
|
|
|
p2->p_pendingcnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Move pending bits to target list */
|
2006-03-02 14:06:40 +00:00
|
|
|
tmp = src->sq_kill;
|
2010-10-13 06:28:40 +00:00
|
|
|
SIGSETAND(tmp, *set);
|
2006-03-02 14:06:40 +00:00
|
|
|
SIGSETOR(dst->sq_kill, tmp);
|
|
|
|
SIGSETNAND(src->sq_kill, tmp);
|
|
|
|
|
2017-02-20 15:53:16 +00:00
|
|
|
tmp = src->sq_ptrace;
|
|
|
|
SIGSETAND(tmp, *set);
|
|
|
|
SIGSETOR(dst->sq_ptrace, tmp);
|
|
|
|
SIGSETNAND(src->sq_ptrace, tmp);
|
|
|
|
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
tmp = src->sq_signals;
|
2010-10-13 06:28:40 +00:00
|
|
|
SIGSETAND(tmp, *set);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
SIGSETOR(dst->sq_signals, tmp);
|
|
|
|
SIGSETNAND(src->sq_signals, tmp);
|
|
|
|
}
|
|
|
|
|
2010-10-14 08:01:33 +00:00
|
|
|
#if 0
|
2010-01-23 11:43:30 +00:00
|
|
|
static void
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sigqueue_move(sigqueue_t *src, sigqueue_t *dst, int signo)
|
|
|
|
{
|
|
|
|
sigset_t set;
|
|
|
|
|
|
|
|
SIGEMPTYSET(set);
|
|
|
|
SIGADDSET(set, signo);
|
|
|
|
sigqueue_move_set(src, dst, &set);
|
|
|
|
}
|
2010-10-14 08:01:33 +00:00
|
|
|
#endif
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
|
2010-01-23 11:43:30 +00:00
|
|
|
static void
|
2010-10-13 06:28:40 +00:00
|
|
|
sigqueue_delete_set(sigqueue_t *sq, const sigset_t *set)
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
{
|
|
|
|
struct proc *p = sq->sq_proc;
|
|
|
|
ksiginfo_t *ksi, *next;
|
|
|
|
|
|
|
|
KASSERT(sq->sq_flags & SQ_INIT, ("src sigqueue not inited"));
|
|
|
|
|
|
|
|
/* Remove siginfo queue */
|
2006-10-22 00:09:41 +00:00
|
|
|
TAILQ_FOREACH_SAFE(ksi, &sq->sq_list, ksi_link, next) {
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
if (SIGISMEMBER(*set, ksi->ksi_signo)) {
|
|
|
|
TAILQ_REMOVE(&sq->sq_list, ksi, ksi_link);
|
2005-10-23 04:12:26 +00:00
|
|
|
ksi->ksi_sigq = NULL;
|
|
|
|
if (ksiginfo_tryfree(ksi) && p != NULL)
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
p->p_pendingcnt--;
|
|
|
|
}
|
|
|
|
}
|
2006-03-02 14:06:40 +00:00
|
|
|
SIGSETNAND(sq->sq_kill, *set);
|
2017-02-20 15:53:16 +00:00
|
|
|
SIGSETNAND(sq->sq_ptrace, *set);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
SIGSETNAND(sq->sq_signals, *set);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
sigqueue_delete(sigqueue_t *sq, int signo)
|
|
|
|
{
|
|
|
|
sigset_t set;
|
|
|
|
|
|
|
|
SIGEMPTYSET(set);
|
|
|
|
SIGADDSET(set, signo);
|
|
|
|
sigqueue_delete_set(sq, &set);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Remove a set of signals for a process */
|
2010-01-23 11:43:30 +00:00
|
|
|
static void
|
2010-10-13 06:28:40 +00:00
|
|
|
sigqueue_delete_set_proc(struct proc *p, const sigset_t *set)
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
{
|
|
|
|
sigqueue_t worklist;
|
|
|
|
struct thread *td0;
|
|
|
|
|
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
|
|
|
|
|
|
|
sigqueue_init(&worklist, NULL);
|
|
|
|
sigqueue_move_set(&p->p_sigqueue, &worklist, set);
|
|
|
|
|
|
|
|
FOREACH_THREAD_IN_PROC(p, td0)
|
|
|
|
sigqueue_move_set(&td0->td_sigqueue, &worklist, set);
|
|
|
|
|
|
|
|
sigqueue_flush(&worklist);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
sigqueue_delete_proc(struct proc *p, int signo)
|
|
|
|
{
|
|
|
|
sigset_t set;
|
|
|
|
|
|
|
|
SIGEMPTYSET(set);
|
|
|
|
SIGADDSET(set, signo);
|
|
|
|
sigqueue_delete_set_proc(p, &set);
|
|
|
|
}
|
|
|
|
|
2010-01-23 11:43:30 +00:00
|
|
|
static void
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sigqueue_delete_stopmask_proc(struct proc *p)
|
|
|
|
{
|
|
|
|
sigset_t set;
|
|
|
|
|
|
|
|
SIGEMPTYSET(set);
|
|
|
|
SIGADDSET(set, SIGSTOP);
|
|
|
|
SIGADDSET(set, SIGTSTP);
|
|
|
|
SIGADDSET(set, SIGTTIN);
|
|
|
|
SIGADDSET(set, SIGTTOU);
|
|
|
|
sigqueue_delete_set_proc(p, &set);
|
|
|
|
}
|
|
|
|
|
2000-09-17 14:28:33 +00:00
|
|
|
/*
|
2013-03-18 18:04:09 +00:00
|
|
|
* Determine signal that should be delivered to thread td, the current
|
|
|
|
* thread, 0 if none. If there is a pending stop signal with default
|
2000-09-17 14:28:33 +00:00
|
|
|
* action, the process stops in issignal().
|
|
|
|
*/
|
|
|
|
int
|
2013-03-18 17:23:58 +00:00
|
|
|
cursig(struct thread *td)
|
2000-09-17 14:28:33 +00:00
|
|
|
{
|
2003-04-01 09:07:36 +00:00
|
|
|
PROC_LOCK_ASSERT(td->td_proc, MA_OWNED);
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_assert(&td->td_proc->p_sigacts->ps_mtx, MA_OWNED);
|
Commit 4/14 of sched_lock decomposition.
- Use thread_lock() rather than sched_lock for per-thread scheduling
sychronization.
- Use the per-process spinlock rather than the sched_lock for per-process
scheduling synchronization.
- Move some common code into thread_suspend_switch() to handle the
mechanics of suspending a thread. The locking here is incredibly
convoluted and should be simplified.
Tested by: kris, current@
Tested on: i386, amd64, ULE, 4BSD, libthr, libkse, PREEMPTION, etc.
Discussed with: kris, attilio, kmacy, jhb, julian, bde (small parts each)
2007-06-04 23:52:24 +00:00
|
|
|
THREAD_LOCK_ASSERT(td, MA_NOTOWNED);
|
2013-03-18 17:23:58 +00:00
|
|
|
return (SIGPENDING(td) ? issignal(td) : 0);
|
2000-09-17 14:28:33 +00:00
|
|
|
}
|
|
|
|
|
2002-04-04 17:49:48 +00:00
|
|
|
/*
|
|
|
|
* Arrange for ast() to handle unmasked pending signals on return to user
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
* mode. This must be called whenever a signal is added to td_sigqueue or
|
2003-03-31 22:49:17 +00:00
|
|
|
* unmasked in td_sigmask.
|
2002-04-04 17:49:48 +00:00
|
|
|
*/
|
|
|
|
void
|
2003-03-31 22:49:17 +00:00
|
|
|
signotify(struct thread *td)
|
2002-04-04 17:49:48 +00:00
|
|
|
{
|
2003-03-31 22:49:17 +00:00
|
|
|
|
2018-05-19 03:57:41 +00:00
|
|
|
PROC_LOCK_ASSERT(td->td_proc, MA_OWNED);
|
2003-03-31 22:49:17 +00:00
|
|
|
|
2003-04-18 20:59:05 +00:00
|
|
|
if (SIGPENDING(td)) {
|
Commit 4/14 of sched_lock decomposition.
- Use thread_lock() rather than sched_lock for per-thread scheduling
sychronization.
- Use the per-process spinlock rather than the sched_lock for per-process
scheduling synchronization.
- Move some common code into thread_suspend_switch() to handle the
mechanics of suspending a thread. The locking here is incredibly
convoluted and should be simplified.
Tested by: kris, current@
Tested on: i386, amd64, ULE, 4BSD, libthr, libkse, PREEMPTION, etc.
Discussed with: kris, attilio, kmacy, jhb, julian, bde (small parts each)
2007-06-04 23:52:24 +00:00
|
|
|
thread_lock(td);
|
2003-03-31 22:49:17 +00:00
|
|
|
td->td_flags |= TDF_NEEDSIGCHK | TDF_ASTPENDING;
|
Commit 4/14 of sched_lock decomposition.
- Use thread_lock() rather than sched_lock for per-thread scheduling
sychronization.
- Use the per-process spinlock rather than the sched_lock for per-process
scheduling synchronization.
- Move some common code into thread_suspend_switch() to handle the
mechanics of suspending a thread. The locking here is incredibly
convoluted and should be simplified.
Tested by: kris, current@
Tested on: i386, amd64, ULE, 4BSD, libthr, libkse, PREEMPTION, etc.
Discussed with: kris, attilio, kmacy, jhb, julian, bde (small parts each)
2007-06-04 23:52:24 +00:00
|
|
|
thread_unlock(td);
|
2003-04-18 20:59:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-27 19:50:58 +00:00
|
|
|
/*
|
|
|
|
* Returns 1 (true) if altstack is configured for the thread, and the
|
|
|
|
* passed stack bottom address falls into the altstack range. Handles
|
|
|
|
* the 43 compat special case where the alt stack size is zero.
|
|
|
|
*/
|
2003-04-18 20:59:05 +00:00
|
|
|
int
|
|
|
|
sigonstack(size_t sp)
|
|
|
|
{
|
2018-11-27 19:50:58 +00:00
|
|
|
struct thread *td;
|
2003-04-18 20:59:05 +00:00
|
|
|
|
2018-11-27 19:50:58 +00:00
|
|
|
td = curthread;
|
|
|
|
if ((td->td_pflags & TDP_ALTSTACK) == 0)
|
|
|
|
return (0);
|
2004-06-11 11:16:26 +00:00
|
|
|
#if defined(COMPAT_43)
|
2019-08-11 19:16:07 +00:00
|
|
|
if (SV_PROC_FLAG(td->td_proc, SV_AOUT) && td->td_sigstk.ss_size == 0)
|
2018-11-27 19:50:58 +00:00
|
|
|
return ((td->td_sigstk.ss_flags & SS_ONSTACK) != 0);
|
2003-04-18 20:59:05 +00:00
|
|
|
#endif
|
2018-11-27 19:50:58 +00:00
|
|
|
return (sp >= (size_t)td->td_sigstk.ss_sp &&
|
|
|
|
sp < td->td_sigstk.ss_size + (size_t)td->td_sigstk.ss_sp);
|
2002-04-04 17:49:48 +00:00
|
|
|
}
|
|
|
|
|
1999-10-12 13:14:18 +00:00
|
|
|
static __inline int
|
|
|
|
sigprop(int sig)
|
1999-09-29 15:03:48 +00:00
|
|
|
{
|
1999-10-12 13:14:18 +00:00
|
|
|
|
2016-09-06 22:03:53 +00:00
|
|
|
if (sig > 0 && sig < nitems(sigproptbl))
|
|
|
|
return (sigproptbl[sig]);
|
1999-10-12 13:14:18 +00:00
|
|
|
return (0);
|
1999-09-29 15:03:48 +00:00
|
|
|
}
|
|
|
|
|
2003-03-31 22:49:17 +00:00
|
|
|
int
|
1999-10-12 13:14:18 +00:00
|
|
|
sig_ffs(sigset_t *set)
|
1999-09-29 15:03:48 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
1999-10-12 13:14:18 +00:00
|
|
|
for (i = 0; i < _SIG_WORDS; i++)
|
1999-09-29 15:03:48 +00:00
|
|
|
if (set->__bits[i])
|
|
|
|
return (ffs(set->__bits[i]) + (i * 32));
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2014-08-22 08:19:08 +00:00
|
|
|
static bool
|
2015-07-10 14:39:46 +00:00
|
|
|
sigact_flag_test(const struct sigaction *act, int flag)
|
2014-08-22 08:19:08 +00:00
|
|
|
{
|
|
|
|
|
2014-08-24 16:37:50 +00:00
|
|
|
/*
|
|
|
|
* SA_SIGINFO is reset when signal disposition is set to
|
|
|
|
* ignore or default. Other flags are kept according to user
|
|
|
|
* settings.
|
|
|
|
*/
|
|
|
|
return ((act->sa_flags & flag) != 0 && (flag != SA_SIGINFO ||
|
|
|
|
((__sighandler_t *)act->sa_sigaction != SIG_IGN &&
|
|
|
|
(__sighandler_t *)act->sa_sigaction != SIG_DFL)));
|
2014-08-22 08:19:08 +00:00
|
|
|
}
|
|
|
|
|
1999-09-29 15:03:48 +00:00
|
|
|
/*
|
2002-09-01 20:37:28 +00:00
|
|
|
* kern_sigaction
|
1999-09-29 15:03:48 +00:00
|
|
|
* sigaction
|
2002-10-25 19:10:58 +00:00
|
|
|
* freebsd4_sigaction
|
1999-09-29 15:03:48 +00:00
|
|
|
* osigaction
|
|
|
|
*/
|
2002-09-01 20:37:28 +00:00
|
|
|
int
|
2015-07-10 14:39:46 +00:00
|
|
|
kern_sigaction(struct thread *td, int sig, const struct sigaction *act,
|
|
|
|
struct sigaction *oact, int flags)
|
1999-09-29 15:03:48 +00:00
|
|
|
{
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
struct sigacts *ps;
|
2002-09-01 20:37:28 +00:00
|
|
|
struct proc *p = td->td_proc;
|
1999-09-29 15:03:48 +00:00
|
|
|
|
2001-11-02 23:50:00 +00:00
|
|
|
if (!_SIG_VALID(sig))
|
1999-09-29 15:03:48 +00:00
|
|
|
return (EINVAL);
|
2015-01-16 07:06:58 +00:00
|
|
|
if (act != NULL && act->sa_handler != SIG_DFL &&
|
|
|
|
act->sa_handler != SIG_IGN && (act->sa_flags & ~(SA_ONSTACK |
|
|
|
|
SA_RESTART | SA_RESETHAND | SA_NOCLDSTOP | SA_NODEFER |
|
|
|
|
SA_NOCLDWAIT | SA_SIGINFO)) != 0)
|
2014-08-22 07:52:47 +00:00
|
|
|
return (EINVAL);
|
1999-09-29 15:03:48 +00:00
|
|
|
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_LOCK(p);
|
|
|
|
ps = p->p_sigacts;
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_lock(&ps->ps_mtx);
|
1999-09-29 15:03:48 +00:00
|
|
|
if (oact) {
|
2018-03-27 18:05:51 +00:00
|
|
|
memset(oact, 0, sizeof(*oact));
|
1999-09-29 15:03:48 +00:00
|
|
|
oact->sa_mask = ps->ps_catchmask[_SIG_IDX(sig)];
|
|
|
|
if (SIGISMEMBER(ps->ps_sigonstack, sig))
|
|
|
|
oact->sa_flags |= SA_ONSTACK;
|
|
|
|
if (!SIGISMEMBER(ps->ps_sigintr, sig))
|
|
|
|
oact->sa_flags |= SA_RESTART;
|
|
|
|
if (SIGISMEMBER(ps->ps_sigreset, sig))
|
|
|
|
oact->sa_flags |= SA_RESETHAND;
|
|
|
|
if (SIGISMEMBER(ps->ps_signodefer, sig))
|
|
|
|
oact->sa_flags |= SA_NODEFER;
|
2007-12-18 20:39:13 +00:00
|
|
|
if (SIGISMEMBER(ps->ps_siginfo, sig)) {
|
1999-09-29 15:03:48 +00:00
|
|
|
oact->sa_flags |= SA_SIGINFO;
|
2007-12-18 20:39:13 +00:00
|
|
|
oact->sa_sigaction =
|
|
|
|
(__siginfohandler_t *)ps->ps_sigact[_SIG_IDX(sig)];
|
|
|
|
} else
|
|
|
|
oact->sa_handler = ps->ps_sigact[_SIG_IDX(sig)];
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
if (sig == SIGCHLD && ps->ps_flag & PS_NOCLDSTOP)
|
1999-09-29 15:03:48 +00:00
|
|
|
oact->sa_flags |= SA_NOCLDSTOP;
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
if (sig == SIGCHLD && ps->ps_flag & PS_NOCLDWAIT)
|
1999-09-29 15:03:48 +00:00
|
|
|
oact->sa_flags |= SA_NOCLDWAIT;
|
|
|
|
}
|
|
|
|
if (act) {
|
|
|
|
if ((sig == SIGKILL || sig == SIGSTOP) &&
|
2001-03-07 02:59:54 +00:00
|
|
|
act->sa_handler != SIG_DFL) {
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_unlock(&ps->ps_mtx);
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_UNLOCK(p);
|
1999-09-29 15:03:48 +00:00
|
|
|
return (EINVAL);
|
2001-03-07 02:59:54 +00:00
|
|
|
}
|
1999-09-29 15:03:48 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Change setting atomically.
|
|
|
|
*/
|
|
|
|
|
|
|
|
ps->ps_catchmask[_SIG_IDX(sig)] = act->sa_mask;
|
|
|
|
SIG_CANTMASK(ps->ps_catchmask[_SIG_IDX(sig)]);
|
2014-08-22 08:19:08 +00:00
|
|
|
if (sigact_flag_test(act, SA_SIGINFO)) {
|
2001-08-01 20:35:24 +00:00
|
|
|
ps->ps_sigact[_SIG_IDX(sig)] =
|
|
|
|
(__sighandler_t *)act->sa_sigaction;
|
2001-10-07 16:11:37 +00:00
|
|
|
SIGADDSET(ps->ps_siginfo, sig);
|
|
|
|
} else {
|
|
|
|
ps->ps_sigact[_SIG_IDX(sig)] = act->sa_handler;
|
1999-09-29 15:03:48 +00:00
|
|
|
SIGDELSET(ps->ps_siginfo, sig);
|
|
|
|
}
|
2014-08-22 08:19:08 +00:00
|
|
|
if (!sigact_flag_test(act, SA_RESTART))
|
1999-09-29 15:03:48 +00:00
|
|
|
SIGADDSET(ps->ps_sigintr, sig);
|
|
|
|
else
|
|
|
|
SIGDELSET(ps->ps_sigintr, sig);
|
2014-08-22 08:19:08 +00:00
|
|
|
if (sigact_flag_test(act, SA_ONSTACK))
|
1999-09-29 15:03:48 +00:00
|
|
|
SIGADDSET(ps->ps_sigonstack, sig);
|
|
|
|
else
|
|
|
|
SIGDELSET(ps->ps_sigonstack, sig);
|
2014-08-22 08:19:08 +00:00
|
|
|
if (sigact_flag_test(act, SA_RESETHAND))
|
1999-09-29 15:03:48 +00:00
|
|
|
SIGADDSET(ps->ps_sigreset, sig);
|
|
|
|
else
|
|
|
|
SIGDELSET(ps->ps_sigreset, sig);
|
2014-08-22 08:19:08 +00:00
|
|
|
if (sigact_flag_test(act, SA_NODEFER))
|
1999-09-29 15:03:48 +00:00
|
|
|
SIGADDSET(ps->ps_signodefer, sig);
|
|
|
|
else
|
|
|
|
SIGDELSET(ps->ps_signodefer, sig);
|
|
|
|
if (sig == SIGCHLD) {
|
|
|
|
if (act->sa_flags & SA_NOCLDSTOP)
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
ps->ps_flag |= PS_NOCLDSTOP;
|
1999-09-29 15:03:48 +00:00
|
|
|
else
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
ps->ps_flag &= ~PS_NOCLDSTOP;
|
2002-04-27 22:41:41 +00:00
|
|
|
if (act->sa_flags & SA_NOCLDWAIT) {
|
1999-09-29 15:03:48 +00:00
|
|
|
/*
|
|
|
|
* Paranoia: since SA_NOCLDWAIT is implemented
|
|
|
|
* by reparenting the dying child to PID 1 (and
|
|
|
|
* trust it to reap the zombie), PID 1 itself
|
|
|
|
* is forbidden to set SA_NOCLDWAIT.
|
|
|
|
*/
|
|
|
|
if (p->p_pid == 1)
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
ps->ps_flag &= ~PS_NOCLDWAIT;
|
1999-09-29 15:03:48 +00:00
|
|
|
else
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
ps->ps_flag |= PS_NOCLDWAIT;
|
1999-09-29 15:03:48 +00:00
|
|
|
} else
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
ps->ps_flag &= ~PS_NOCLDWAIT;
|
2002-04-27 22:41:41 +00:00
|
|
|
if (ps->ps_sigact[_SIG_IDX(SIGCHLD)] == SIG_IGN)
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
ps->ps_flag |= PS_CLDSIGIGN;
|
2002-04-27 22:41:41 +00:00
|
|
|
else
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
ps->ps_flag &= ~PS_CLDSIGIGN;
|
1999-09-29 15:03:48 +00:00
|
|
|
}
|
|
|
|
/*
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
* Set bit in ps_sigignore for signals that are set to SIG_IGN,
|
1999-09-29 15:03:48 +00:00
|
|
|
* and for signals set to SIG_DFL where the default is to
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
* ignore. However, don't put SIGCONT in ps_sigignore, as we
|
1999-09-29 15:03:48 +00:00
|
|
|
* have to restart the process.
|
|
|
|
*/
|
|
|
|
if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN ||
|
2016-09-02 18:22:56 +00:00
|
|
|
(sigprop(sig) & SIGPROP_IGNORE &&
|
1999-09-29 15:03:48 +00:00
|
|
|
ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL)) {
|
|
|
|
/* never to be seen again */
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sigqueue_delete_proc(p, sig);
|
1999-09-29 15:03:48 +00:00
|
|
|
if (sig != SIGCONT)
|
|
|
|
/* easier in psignal */
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
SIGADDSET(ps->ps_sigignore, sig);
|
|
|
|
SIGDELSET(ps->ps_sigcatch, sig);
|
1999-10-11 20:33:17 +00:00
|
|
|
} else {
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
SIGDELSET(ps->ps_sigignore, sig);
|
1999-09-29 15:03:48 +00:00
|
|
|
if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL)
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
SIGDELSET(ps->ps_sigcatch, sig);
|
1999-09-29 15:03:48 +00:00
|
|
|
else
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
SIGADDSET(ps->ps_sigcatch, sig);
|
1999-09-29 15:03:48 +00:00
|
|
|
}
|
2002-10-25 19:10:58 +00:00
|
|
|
#ifdef COMPAT_FREEBSD4
|
|
|
|
if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN ||
|
|
|
|
ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL ||
|
|
|
|
(flags & KSA_FREEBSD4) == 0)
|
|
|
|
SIGDELSET(ps->ps_freebsd4, sig);
|
|
|
|
else
|
|
|
|
SIGADDSET(ps->ps_freebsd4, sig);
|
|
|
|
#endif
|
2001-08-21 02:32:59 +00:00
|
|
|
#ifdef COMPAT_43
|
1999-10-11 20:33:17 +00:00
|
|
|
if (ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN ||
|
2002-10-25 19:10:58 +00:00
|
|
|
ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL ||
|
|
|
|
(flags & KSA_OSIGSET) == 0)
|
1999-10-11 20:33:17 +00:00
|
|
|
SIGDELSET(ps->ps_osigset, sig);
|
|
|
|
else
|
|
|
|
SIGADDSET(ps->ps_osigset, sig);
|
2001-08-21 02:32:59 +00:00
|
|
|
#endif
|
1999-09-29 15:03:48 +00:00
|
|
|
}
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_unlock(&ps->ps_mtx);
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_UNLOCK(p);
|
1999-09-29 15:03:48 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct sigaction_args {
|
1999-09-29 15:03:48 +00:00
|
|
|
int sig;
|
|
|
|
struct sigaction *act;
|
|
|
|
struct sigaction *oact;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
sys_sigaction(struct thread *td, struct sigaction_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
1999-09-29 15:03:48 +00:00
|
|
|
struct sigaction act, oact;
|
2017-03-02 22:17:53 +00:00
|
|
|
struct sigaction *actp, *oactp;
|
1999-09-29 15:03:48 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1999-10-12 13:14:18 +00:00
|
|
|
actp = (uap->act != NULL) ? &act : NULL;
|
|
|
|
oactp = (uap->oact != NULL) ? &oact : NULL;
|
1999-09-29 15:03:48 +00:00
|
|
|
if (actp) {
|
1999-10-12 13:14:18 +00:00
|
|
|
error = copyin(uap->act, actp, sizeof(act));
|
1999-09-29 15:03:48 +00:00
|
|
|
if (error)
|
2003-02-15 09:56:09 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2002-09-01 20:37:28 +00:00
|
|
|
error = kern_sigaction(td, uap->sig, actp, oactp, 0);
|
2003-04-25 20:01:19 +00:00
|
|
|
if (oactp && !error)
|
1999-10-12 13:14:18 +00:00
|
|
|
error = copyout(oactp, uap->oact, sizeof(oact));
|
1999-09-29 15:03:48 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2002-10-25 19:10:58 +00:00
|
|
|
#ifdef COMPAT_FREEBSD4
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct freebsd4_sigaction_args {
|
|
|
|
int sig;
|
|
|
|
struct sigaction *act;
|
|
|
|
struct sigaction *oact;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
freebsd4_sigaction(struct thread *td, struct freebsd4_sigaction_args *uap)
|
2002-10-25 19:10:58 +00:00
|
|
|
{
|
|
|
|
struct sigaction act, oact;
|
2017-03-02 22:17:53 +00:00
|
|
|
struct sigaction *actp, *oactp;
|
2002-10-25 19:10:58 +00:00
|
|
|
int error;
|
|
|
|
|
|
|
|
actp = (uap->act != NULL) ? &act : NULL;
|
|
|
|
oactp = (uap->oact != NULL) ? &oact : NULL;
|
|
|
|
if (actp) {
|
|
|
|
error = copyin(uap->act, actp, sizeof(act));
|
|
|
|
if (error)
|
2003-02-15 09:56:09 +00:00
|
|
|
return (error);
|
2002-10-25 19:10:58 +00:00
|
|
|
}
|
|
|
|
error = kern_sigaction(td, uap->sig, actp, oactp, KSA_FREEBSD4);
|
2003-04-30 19:45:13 +00:00
|
|
|
if (oactp && !error)
|
2002-10-25 19:10:58 +00:00
|
|
|
error = copyout(oactp, uap->oact, sizeof(oact));
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
#endif /* COMAPT_FREEBSD4 */
|
|
|
|
|
2000-08-26 02:27:01 +00:00
|
|
|
#ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */
|
1999-09-29 15:03:48 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct osigaction_args {
|
|
|
|
int signum;
|
|
|
|
struct osigaction *nsa;
|
|
|
|
struct osigaction *osa;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
osigaction(struct thread *td, struct osigaction_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
1999-09-29 15:03:48 +00:00
|
|
|
struct osigaction sa;
|
|
|
|
struct sigaction nsa, osa;
|
2017-03-02 22:17:53 +00:00
|
|
|
struct sigaction *nsap, *osap;
|
1999-09-29 15:03:48 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1999-10-12 13:14:18 +00:00
|
|
|
if (uap->signum <= 0 || uap->signum >= ONSIG)
|
|
|
|
return (EINVAL);
|
2001-09-01 18:19:21 +00:00
|
|
|
|
1999-10-12 13:14:18 +00:00
|
|
|
nsap = (uap->nsa != NULL) ? &nsa : NULL;
|
|
|
|
osap = (uap->osa != NULL) ? &osa : NULL;
|
2001-09-01 18:19:21 +00:00
|
|
|
|
1999-09-29 15:03:48 +00:00
|
|
|
if (nsap) {
|
1999-10-12 13:14:18 +00:00
|
|
|
error = copyin(uap->nsa, &sa, sizeof(sa));
|
1999-09-29 15:03:48 +00:00
|
|
|
if (error)
|
2003-02-15 09:56:09 +00:00
|
|
|
return (error);
|
1999-09-29 15:03:48 +00:00
|
|
|
nsap->sa_handler = sa.sa_handler;
|
|
|
|
nsap->sa_flags = sa.sa_flags;
|
|
|
|
OSIG2SIG(sa.sa_mask, nsap->sa_mask);
|
Implement SA_SIGINFO for i386. Thanks to Bruce Evans for much more
than a review, this was a nice puzzle.
This is supposed to be binary and source compatible with older
applications that access the old FreeBSD-style three arguments to a
signal handler.
Except those applications that access hidden signal handler arguments
bejond the documented third one. If you have applications that do,
please let me know so that we take the opportunity to provide the
functionality they need in a documented manner.
Also except application that use 'struct sigframe' directly. You need
to recompile gdb and doscmd. `make world` is recommended.
Example program that demonstrates how SA_SIGINFO and old-style FreeBSD
handlers (with their three args) may be used in the same process is at
http://www3.cons.org/tmp/fbsd-siginfo.c
Programs that use the old FreeBSD-style three arguments are easy to
change to SA_SIGINFO (although they don't need to, since the old style
will still work):
Old args to signal handler:
void handler_sn(int sig, int code, struct sigcontext *scp)
New args:
void handler_si(int sig, siginfo_t *si, void *third)
where:
old:code == new:second->si_code
old:scp == &(new:si->si_scp) /* Passed by value! */
The latter is also pointed to by new:third, but accessing via
si->si_scp is preferred because it is type-save.
FreeBSD implementation notes:
- This is just the framework to make the interface POSIX compatible.
For now, no additional functionality is provided. This is supposed
to happen now, starting with floating point values.
- We don't use 'sigcontext_t.si_value' for now (POSIX meant it for
realtime-related values).
- Documentation will be updated when new functionality is added and
the exact arguments passed are determined. The comments in
sys/signal.h are meant to be useful.
Reviewed by: BDE
1999-07-06 07:13:48 +00:00
|
|
|
}
|
2002-10-25 19:10:58 +00:00
|
|
|
error = kern_sigaction(td, uap->signum, nsap, osap, KSA_OSIGSET);
|
1999-09-29 15:03:48 +00:00
|
|
|
if (osap && !error) {
|
|
|
|
sa.sa_handler = osap->sa_handler;
|
|
|
|
sa.sa_flags = osap->sa_flags;
|
|
|
|
SIG2OSIG(osap->sa_mask, sa.sa_mask);
|
1999-10-12 13:14:18 +00:00
|
|
|
error = copyout(&sa, uap->osa, sizeof(sa));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
1999-09-29 15:03:48 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2002-10-25 19:10:58 +00:00
|
|
|
|
2006-05-12 05:04:46 +00:00
|
|
|
#if !defined(__i386__)
|
2002-10-25 19:10:58 +00:00
|
|
|
/* Avoid replicating the same stub everywhere */
|
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
osigreturn(struct thread *td, struct osigreturn_args *uap)
|
2002-10-25 19:10:58 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (nosys(td, (struct nosys_args *)uap));
|
|
|
|
}
|
|
|
|
#endif
|
2000-08-26 02:27:01 +00:00
|
|
|
#endif /* COMPAT_43 */
|
1994-05-24 10:09:53 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize signal state for process 0;
|
|
|
|
* set to ignore signals that are ignored by default.
|
|
|
|
*/
|
|
|
|
void
|
2017-03-02 22:17:53 +00:00
|
|
|
siginit(struct proc *p)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2017-05-17 00:34:34 +00:00
|
|
|
int i;
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
struct sigacts *ps;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_LOCK(p);
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
ps = p->p_sigacts;
|
|
|
|
mtx_lock(&ps->ps_mtx);
|
2014-08-22 08:19:08 +00:00
|
|
|
for (i = 1; i <= NSIG; i++) {
|
2016-09-02 18:22:56 +00:00
|
|
|
if (sigprop(i) & SIGPROP_IGNORE && i != SIGCONT) {
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
SIGADDSET(ps->ps_sigignore, i);
|
2014-08-22 08:19:08 +00:00
|
|
|
}
|
|
|
|
}
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_unlock(&ps->ps_mtx);
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_UNLOCK(p);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2014-08-22 08:19:08 +00:00
|
|
|
/*
|
|
|
|
* Reset specified signal to the default disposition.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
sigdflt(struct sigacts *ps, int sig)
|
|
|
|
{
|
|
|
|
|
|
|
|
mtx_assert(&ps->ps_mtx, MA_OWNED);
|
|
|
|
SIGDELSET(ps->ps_sigcatch, sig);
|
2016-09-02 18:22:56 +00:00
|
|
|
if ((sigprop(sig) & SIGPROP_IGNORE) != 0 && sig != SIGCONT)
|
2014-08-22 08:19:08 +00:00
|
|
|
SIGADDSET(ps->ps_sigignore, sig);
|
|
|
|
ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL;
|
|
|
|
SIGDELSET(ps->ps_siginfo, sig);
|
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Reset signals for an exec of the specified process.
|
|
|
|
*/
|
|
|
|
void
|
2004-01-03 02:02:26 +00:00
|
|
|
execsigs(struct proc *p)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2015-08-12 11:30:31 +00:00
|
|
|
sigset_t osigignore;
|
2004-01-03 02:02:26 +00:00
|
|
|
struct sigacts *ps;
|
|
|
|
int sig;
|
|
|
|
struct thread *td;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Reset caught signals. Held signals remain held
|
2003-03-31 22:49:17 +00:00
|
|
|
* through td_sigmask (unless they were caught,
|
1994-05-24 10:09:53 +00:00
|
|
|
* and are now ignored by default).
|
|
|
|
*/
|
2002-05-02 15:00:14 +00:00
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
2001-03-07 02:59:54 +00:00
|
|
|
ps = p->p_sigacts;
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_lock(&ps->ps_mtx);
|
2019-09-25 19:20:41 +00:00
|
|
|
sig_drop_caught(p);
|
2015-08-12 11:30:31 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* As CloudABI processes cannot modify signal handlers, fully
|
|
|
|
* reset all signals to their default behavior. Do ignore
|
|
|
|
* SIGPIPE, as it would otherwise be impossible to recover from
|
|
|
|
* writes to broken pipes and sockets.
|
|
|
|
*/
|
|
|
|
if (SV_PROC_ABI(p) == SV_ABI_CLOUDABI) {
|
|
|
|
osigignore = ps->ps_sigignore;
|
|
|
|
while (SIGNOTEMPTY(osigignore)) {
|
|
|
|
sig = sig_ffs(&osigignore);
|
|
|
|
SIGDELSET(osigignore, sig);
|
|
|
|
if (sig != SIGPIPE)
|
|
|
|
sigdflt(ps, sig);
|
|
|
|
}
|
|
|
|
SIGADDSET(ps->ps_sigignore, SIGPIPE);
|
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Reset stack state to the user stack.
|
|
|
|
* Clear set of signals caught on the signal stack.
|
|
|
|
*/
|
2017-03-17 13:37:37 +00:00
|
|
|
td = curthread;
|
|
|
|
MPASS(td->td_proc == p);
|
2004-01-03 02:02:26 +00:00
|
|
|
td->td_sigstk.ss_flags = SS_DISABLE;
|
|
|
|
td->td_sigstk.ss_size = 0;
|
|
|
|
td->td_sigstk.ss_sp = 0;
|
|
|
|
td->td_pflags &= ~TDP_ALTSTACK;
|
1999-07-18 13:40:11 +00:00
|
|
|
/*
|
|
|
|
* Reset no zombies if child dies flag as Solaris does.
|
|
|
|
*/
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
ps->ps_flag &= ~(PS_NOCLDWAIT | PS_CLDSIGIGN);
|
2001-06-11 09:15:41 +00:00
|
|
|
if (ps->ps_sigact[_SIG_IDX(SIGCHLD)] == SIG_IGN)
|
|
|
|
ps->ps_sigact[_SIG_IDX(SIGCHLD)] = SIG_DFL;
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_unlock(&ps->ps_mtx);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2003-04-18 20:18:44 +00:00
|
|
|
* kern_sigprocmask()
|
2000-04-02 17:52:43 +00:00
|
|
|
*
|
2001-03-07 02:59:54 +00:00
|
|
|
* Manipulate signal mask.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2003-04-18 20:18:44 +00:00
|
|
|
int
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
kern_sigprocmask(struct thread *td, int how, sigset_t *set, sigset_t *oset,
|
2009-10-27 10:42:24 +00:00
|
|
|
int flags)
|
1999-09-29 15:03:48 +00:00
|
|
|
{
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
sigset_t new_block, oset1;
|
|
|
|
struct proc *p;
|
1999-09-29 15:03:48 +00:00
|
|
|
int error;
|
|
|
|
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
p = td->td_proc;
|
2014-11-28 10:20:00 +00:00
|
|
|
if ((flags & SIGPROCMASK_PROC_LOCKED) != 0)
|
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
|
|
|
else
|
2009-10-27 10:42:24 +00:00
|
|
|
PROC_LOCK(p);
|
2014-11-28 10:20:00 +00:00
|
|
|
mtx_assert(&p->p_sigacts->ps_mtx, (flags & SIGPROCMASK_PS_LOCKED) != 0
|
|
|
|
? MA_OWNED : MA_NOTOWNED);
|
1999-09-29 15:03:48 +00:00
|
|
|
if (oset != NULL)
|
2003-03-31 22:49:17 +00:00
|
|
|
*oset = td->td_sigmask;
|
1999-09-29 15:03:48 +00:00
|
|
|
|
|
|
|
error = 0;
|
|
|
|
if (set != NULL) {
|
|
|
|
switch (how) {
|
|
|
|
case SIG_BLOCK:
|
1999-10-11 20:33:17 +00:00
|
|
|
SIG_CANTMASK(*set);
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
oset1 = td->td_sigmask;
|
2003-03-31 22:49:17 +00:00
|
|
|
SIGSETOR(td->td_sigmask, *set);
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
new_block = td->td_sigmask;
|
|
|
|
SIGSETNAND(new_block, oset1);
|
1999-09-29 15:03:48 +00:00
|
|
|
break;
|
|
|
|
case SIG_UNBLOCK:
|
2003-03-31 22:49:17 +00:00
|
|
|
SIGSETNAND(td->td_sigmask, *set);
|
|
|
|
signotify(td);
|
2010-10-14 08:01:33 +00:00
|
|
|
goto out;
|
1999-09-29 15:03:48 +00:00
|
|
|
case SIG_SETMASK:
|
1999-10-11 20:33:17 +00:00
|
|
|
SIG_CANTMASK(*set);
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
oset1 = td->td_sigmask;
|
2009-10-27 10:42:24 +00:00
|
|
|
if (flags & SIGPROCMASK_OLD)
|
2003-03-31 22:49:17 +00:00
|
|
|
SIGSETLO(td->td_sigmask, *set);
|
1999-10-11 20:33:17 +00:00
|
|
|
else
|
2003-03-31 22:49:17 +00:00
|
|
|
td->td_sigmask = *set;
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
new_block = td->td_sigmask;
|
|
|
|
SIGSETNAND(new_block, oset1);
|
2003-03-31 22:49:17 +00:00
|
|
|
signotify(td);
|
1999-09-29 15:03:48 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error = EINVAL;
|
2010-10-14 08:01:33 +00:00
|
|
|
goto out;
|
1999-09-29 15:03:48 +00:00
|
|
|
}
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
|
2010-10-14 08:01:33 +00:00
|
|
|
/*
|
|
|
|
* The new_block set contains signals that were not previously
|
|
|
|
* blocked, but are blocked now.
|
|
|
|
*
|
|
|
|
* In case we block any signal that was not previously blocked
|
|
|
|
* for td, and process has the signal pending, try to schedule
|
|
|
|
* signal delivery to some thread that does not block the
|
|
|
|
* signal, possibly waking it up.
|
|
|
|
*/
|
|
|
|
if (p->p_numthreads != 1)
|
|
|
|
reschedule_signals(p, new_block, flags);
|
|
|
|
}
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
|
2010-10-14 08:01:33 +00:00
|
|
|
out:
|
2009-10-27 10:42:24 +00:00
|
|
|
if (!(flags & SIGPROCMASK_PROC_LOCKED))
|
|
|
|
PROC_UNLOCK(p);
|
1999-09-29 15:03:48 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct sigprocmask_args {
|
|
|
|
int how;
|
1999-09-29 15:03:48 +00:00
|
|
|
const sigset_t *set;
|
|
|
|
sigset_t *oset;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
sys_sigprocmask(struct thread *td, struct sigprocmask_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
1999-09-29 15:03:48 +00:00
|
|
|
sigset_t set, oset;
|
|
|
|
sigset_t *setp, *osetp;
|
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1999-10-12 13:14:18 +00:00
|
|
|
setp = (uap->set != NULL) ? &set : NULL;
|
|
|
|
osetp = (uap->oset != NULL) ? &oset : NULL;
|
1999-09-29 15:03:48 +00:00
|
|
|
if (setp) {
|
1999-10-12 13:14:18 +00:00
|
|
|
error = copyin(uap->set, setp, sizeof(set));
|
1999-09-29 15:03:48 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
}
|
2003-04-18 20:18:44 +00:00
|
|
|
error = kern_sigprocmask(td, uap->how, setp, osetp, 0);
|
1999-09-29 15:03:48 +00:00
|
|
|
if (osetp && !error) {
|
1999-10-12 13:14:18 +00:00
|
|
|
error = copyout(osetp, uap->oset, sizeof(oset));
|
1999-09-29 15:03:48 +00:00
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2000-08-26 02:27:01 +00:00
|
|
|
#ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */
|
1999-09-29 15:03:48 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct osigprocmask_args {
|
|
|
|
int how;
|
|
|
|
osigset_t mask;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
osigprocmask(struct thread *td, struct osigprocmask_args *uap)
|
1999-09-29 15:03:48 +00:00
|
|
|
{
|
|
|
|
sigset_t set, oset;
|
|
|
|
int error;
|
1995-05-30 08:16:23 +00:00
|
|
|
|
1999-09-29 15:03:48 +00:00
|
|
|
OSIG2SIG(uap->mask, set);
|
2003-04-18 20:18:44 +00:00
|
|
|
error = kern_sigprocmask(td, uap->how, &set, &oset, 1);
|
2001-09-12 08:38:13 +00:00
|
|
|
SIG2OSIG(oset, td->td_retval[0]);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
|
|
|
}
|
2000-08-26 02:27:01 +00:00
|
|
|
#endif /* COMPAT_43 */
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2003-03-31 23:30:41 +00:00
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_sigwait(struct thread *td, struct sigwait_args *uap)
|
2003-03-31 23:30:41 +00:00
|
|
|
{
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
ksiginfo_t ksi;
|
2003-03-31 23:30:41 +00:00
|
|
|
sigset_t set;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = copyin(uap->set, &set, sizeof(set));
|
2004-06-07 13:35:02 +00:00
|
|
|
if (error) {
|
|
|
|
td->td_retval[0] = error;
|
|
|
|
return (0);
|
|
|
|
}
|
2003-03-31 23:30:41 +00:00
|
|
|
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
error = kern_sigtimedwait(td, set, &ksi, NULL);
|
2004-06-07 13:35:02 +00:00
|
|
|
if (error) {
|
2011-10-01 10:18:55 +00:00
|
|
|
if (error == EINTR && td->td_proc->p_osrel < P_OSREL_SIGWAIT)
|
|
|
|
error = ERESTART;
|
2004-06-07 13:35:02 +00:00
|
|
|
if (error == ERESTART)
|
|
|
|
return (error);
|
|
|
|
td->td_retval[0] = error;
|
|
|
|
return (0);
|
|
|
|
}
|
2003-03-31 23:30:41 +00:00
|
|
|
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
error = copyout(&ksi.ksi_signo, uap->sig, sizeof(ksi.ksi_signo));
|
2004-06-07 13:35:02 +00:00
|
|
|
td->td_retval[0] = error;
|
|
|
|
return (0);
|
2003-03-31 23:30:41 +00:00
|
|
|
}
|
2007-03-04 22:36:48 +00:00
|
|
|
|
2003-03-31 23:30:41 +00:00
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_sigtimedwait(struct thread *td, struct sigtimedwait_args *uap)
|
2003-03-31 23:30:41 +00:00
|
|
|
{
|
|
|
|
struct timespec ts;
|
|
|
|
struct timespec *timeout;
|
|
|
|
sigset_t set;
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
ksiginfo_t ksi;
|
2003-03-31 23:30:41 +00:00
|
|
|
int error;
|
|
|
|
|
|
|
|
if (uap->timeout) {
|
|
|
|
error = copyin(uap->timeout, &ts, sizeof(ts));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
timeout = &ts;
|
|
|
|
} else
|
|
|
|
timeout = NULL;
|
|
|
|
|
|
|
|
error = copyin(uap->set, &set, sizeof(set));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
error = kern_sigtimedwait(td, set, &ksi, timeout);
|
2003-03-31 23:30:41 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
o Change kse_thr_interrupt to allow send a signal to a specified thread,
or unblock a thread in kernel, and allow UTS to specify whether syscall
should be restarted.
o Add ability for UTS to monitor signal comes in and removed from process,
the flag PS_SIGEVENT is used to indicate the events.
o Add a KMF_WAITSIGEVENT for KSE mailbox flag, UTS call kse_release with
this flag set to wait for above signal event.
o For SA based thread, kernel masks all signal in its signal mask, let
UTS to use kse_thr_interrupt interrupt a thread, and install a signal
frame in userland for the thread.
o Add a tm_syncsig in thread mailbox, when a hardware trap occurs,
it is used to deliver synchronous signal to userland, and upcall
is schedule, so UTS can process the synchronous signal for the thread.
Reviewed by: julian (mentor)
2003-06-28 08:29:05 +00:00
|
|
|
|
2003-06-28 08:03:28 +00:00
|
|
|
if (uap->info)
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
error = copyout(&ksi.ksi_info, uap->info, sizeof(siginfo_t));
|
|
|
|
|
|
|
|
if (error == 0)
|
|
|
|
td->td_retval[0] = ksi.ksi_signo;
|
2003-03-31 23:30:41 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_sigwaitinfo(struct thread *td, struct sigwaitinfo_args *uap)
|
2003-03-31 23:30:41 +00:00
|
|
|
{
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
ksiginfo_t ksi;
|
2003-03-31 23:30:41 +00:00
|
|
|
sigset_t set;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = copyin(uap->set, &set, sizeof(set));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
error = kern_sigtimedwait(td, set, &ksi, NULL);
|
2003-03-31 23:30:41 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
2003-06-28 08:03:28 +00:00
|
|
|
if (uap->info)
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
error = copyout(&ksi.ksi_info, uap->info, sizeof(siginfo_t));
|
2012-11-27 10:11:54 +00:00
|
|
|
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
if (error == 0)
|
|
|
|
td->td_retval[0] = ksi.ksi_signo;
|
2003-03-31 23:30:41 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2017-03-30 18:21:36 +00:00
|
|
|
static void
|
|
|
|
proc_td_siginfo_capture(struct thread *td, siginfo_t *si)
|
|
|
|
{
|
|
|
|
struct thread *thr;
|
|
|
|
|
|
|
|
FOREACH_THREAD_IN_PROC(td->td_proc, thr) {
|
|
|
|
if (thr == td)
|
|
|
|
thr->td_si = *si;
|
|
|
|
else
|
|
|
|
thr->td_si.si_signo = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-05 01:56:11 +00:00
|
|
|
int
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
kern_sigtimedwait(struct thread *td, sigset_t waitset, ksiginfo_t *ksi,
|
|
|
|
struct timespec *timeout)
|
2003-03-31 23:30:41 +00:00
|
|
|
{
|
2003-07-17 22:52:55 +00:00
|
|
|
struct sigacts *ps;
|
2010-10-14 08:01:33 +00:00
|
|
|
sigset_t saved_mask, new_block;
|
2003-07-17 22:52:55 +00:00
|
|
|
struct proc *p;
|
2010-10-14 08:01:33 +00:00
|
|
|
int error, sig, timo, timevalid = 0;
|
2005-02-19 06:05:49 +00:00
|
|
|
struct timespec rts, ets, ts;
|
|
|
|
struct timeval tv;
|
2019-11-27 20:33:53 +00:00
|
|
|
bool traced;
|
2003-03-31 23:30:41 +00:00
|
|
|
|
|
|
|
p = td->td_proc;
|
|
|
|
error = 0;
|
2007-06-10 01:43:11 +00:00
|
|
|
ets.tv_sec = 0;
|
|
|
|
ets.tv_nsec = 0;
|
2019-11-27 20:33:53 +00:00
|
|
|
traced = false;
|
2003-03-31 23:30:41 +00:00
|
|
|
|
2010-10-14 08:01:33 +00:00
|
|
|
if (timeout != NULL) {
|
2005-02-19 06:05:49 +00:00
|
|
|
if (timeout->tv_nsec >= 0 && timeout->tv_nsec < 1000000000) {
|
|
|
|
timevalid = 1;
|
|
|
|
getnanouptime(&rts);
|
Make timespecadd(3) and friends public
The timespecadd(3) family of macros were imported from NetBSD back in
r35029. However, they were initially guarded by #ifdef _KERNEL. In the
meantime, we have grown at least 28 syscalls that use timespecs in some
way, leading many programs both inside and outside of the base system to
redefine those macros. It's better just to make the definitions public.
Our kernel currently defines two-argument versions of timespecadd and
timespecsub. NetBSD, OpenBSD, and FreeDesktop.org's libbsd, however, define
three-argument versions. Solaris also defines a three-argument version, but
only in its kernel. This revision changes our definition to match the
common three-argument version.
Bump _FreeBSD_version due to the breaking KPI change.
Discussed with: cem, jilles, ian, bde
Differential Revision: https://reviews.freebsd.org/D14725
2018-07-30 15:46:40 +00:00
|
|
|
timespecadd(&rts, timeout, &ets);
|
2005-02-19 06:05:49 +00:00
|
|
|
}
|
|
|
|
}
|
2010-10-14 08:01:33 +00:00
|
|
|
ksiginfo_init(ksi);
|
|
|
|
/* Some signals can not be waited for. */
|
|
|
|
SIG_CANTMASK(waitset);
|
|
|
|
ps = p->p_sigacts;
|
|
|
|
PROC_LOCK(p);
|
|
|
|
saved_mask = td->td_sigmask;
|
|
|
|
SIGSETNAND(td->td_sigmask, waitset);
|
|
|
|
for (;;) {
|
2006-02-23 09:24:19 +00:00
|
|
|
mtx_lock(&ps->ps_mtx);
|
2013-03-18 17:23:58 +00:00
|
|
|
sig = cursig(td);
|
2006-02-23 09:24:19 +00:00
|
|
|
mtx_unlock(&ps->ps_mtx);
|
2016-07-03 18:19:48 +00:00
|
|
|
KASSERT(sig >= 0, ("sig %d", sig));
|
2010-10-14 08:01:33 +00:00
|
|
|
if (sig != 0 && SIGISMEMBER(waitset, sig)) {
|
|
|
|
if (sigqueue_get(&td->td_sigqueue, sig, ksi) != 0 ||
|
2012-11-27 10:11:54 +00:00
|
|
|
sigqueue_get(&p->p_sigqueue, sig, ksi) != 0) {
|
2010-10-14 08:01:33 +00:00
|
|
|
error = 0;
|
|
|
|
break;
|
|
|
|
}
|
2006-02-23 09:24:19 +00:00
|
|
|
}
|
|
|
|
|
2010-10-14 08:01:33 +00:00
|
|
|
if (error != 0)
|
|
|
|
break;
|
2003-03-31 23:30:41 +00:00
|
|
|
|
2010-10-14 08:01:33 +00:00
|
|
|
/*
|
|
|
|
* POSIX says this must be checked after looking for pending
|
|
|
|
* signals.
|
|
|
|
*/
|
|
|
|
if (timeout != NULL) {
|
|
|
|
if (!timevalid) {
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
getnanouptime(&rts);
|
|
|
|
if (timespeccmp(&rts, &ets, >=)) {
|
|
|
|
error = EAGAIN;
|
|
|
|
break;
|
|
|
|
}
|
Make timespecadd(3) and friends public
The timespecadd(3) family of macros were imported from NetBSD back in
r35029. However, they were initially guarded by #ifdef _KERNEL. In the
meantime, we have grown at least 28 syscalls that use timespecs in some
way, leading many programs both inside and outside of the base system to
redefine those macros. It's better just to make the definitions public.
Our kernel currently defines two-argument versions of timespecadd and
timespecsub. NetBSD, OpenBSD, and FreeDesktop.org's libbsd, however, define
three-argument versions. Solaris also defines a three-argument version, but
only in its kernel. This revision changes our definition to match the
common three-argument version.
Bump _FreeBSD_version due to the breaking KPI change.
Discussed with: cem, jilles, ian, bde
Differential Revision: https://reviews.freebsd.org/D14725
2018-07-30 15:46:40 +00:00
|
|
|
timespecsub(&ets, &rts, &ts);
|
2010-10-14 08:01:33 +00:00
|
|
|
TIMESPEC_TO_TIMEVAL(&tv, &ts);
|
|
|
|
timo = tvtohz(&tv);
|
|
|
|
} else {
|
|
|
|
timo = 0;
|
2003-07-17 22:52:55 +00:00
|
|
|
}
|
2003-03-31 23:30:41 +00:00
|
|
|
|
2019-11-27 20:33:53 +00:00
|
|
|
if (traced) {
|
|
|
|
error = EINTR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-10-14 08:01:33 +00:00
|
|
|
error = msleep(ps, &p->p_mtx, PPAUSE|PCATCH, "sigwait", timo);
|
|
|
|
|
|
|
|
if (timeout != NULL) {
|
|
|
|
if (error == ERESTART) {
|
|
|
|
/* Timeout can not be restarted. */
|
|
|
|
error = EINTR;
|
|
|
|
} else if (error == EAGAIN) {
|
|
|
|
/* We will calculate timeout by ourself. */
|
|
|
|
error = 0;
|
|
|
|
}
|
2005-02-19 06:05:49 +00:00
|
|
|
}
|
2019-11-27 20:33:53 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If PTRACE_SCE or PTRACE_SCX were set after
|
|
|
|
* userspace entered the syscall, return spurious
|
|
|
|
* EINTR after wait was done. Only do this as last
|
|
|
|
* resort after rechecking for possible queued signals
|
|
|
|
* and expired timeouts.
|
|
|
|
*/
|
|
|
|
if (error == 0 && (p->p_ptevents & PTRACE_SYSCALL) != 0)
|
|
|
|
traced = true;
|
2005-02-19 06:05:49 +00:00
|
|
|
}
|
o Change kse_thr_interrupt to allow send a signal to a specified thread,
or unblock a thread in kernel, and allow UTS to specify whether syscall
should be restarted.
o Add ability for UTS to monitor signal comes in and removed from process,
the flag PS_SIGEVENT is used to indicate the events.
o Add a KMF_WAITSIGEVENT for KSE mailbox flag, UTS call kse_release with
this flag set to wait for above signal event.
o For SA based thread, kernel masks all signal in its signal mask, let
UTS to use kse_thr_interrupt interrupt a thread, and install a signal
frame in userland for the thread.
o Add a tm_syncsig in thread mailbox, when a hardware trap occurs,
it is used to deliver synchronous signal to userland, and upcall
is schedule, so UTS can process the synchronous signal for the thread.
Reviewed by: julian (mentor)
2003-06-28 08:29:05 +00:00
|
|
|
|
2010-10-14 08:01:33 +00:00
|
|
|
new_block = saved_mask;
|
|
|
|
SIGSETNAND(new_block, td->td_sigmask);
|
|
|
|
td->td_sigmask = saved_mask;
|
|
|
|
/*
|
|
|
|
* Fewer signals can be delivered to us, reschedule signal
|
|
|
|
* notification.
|
|
|
|
*/
|
|
|
|
if (p->p_numthreads != 1)
|
|
|
|
reschedule_signals(p, new_block, 0);
|
2008-05-24 06:22:16 +00:00
|
|
|
|
2010-10-14 08:01:33 +00:00
|
|
|
if (error == 0) {
|
2015-12-16 23:39:27 +00:00
|
|
|
SDT_PROBE2(proc, , , signal__clear, sig, ksi);
|
2012-11-27 10:11:54 +00:00
|
|
|
|
2005-10-30 02:56:08 +00:00
|
|
|
if (ksi->ksi_code == SI_TIMER)
|
|
|
|
itimer_accept(p, ksi->ksi_timerid, ksi);
|
2006-02-23 09:24:19 +00:00
|
|
|
|
2003-03-31 23:30:41 +00:00
|
|
|
#ifdef KTRACE
|
2006-02-23 09:24:19 +00:00
|
|
|
if (KTRPOINT(td, KTR_PSIG)) {
|
|
|
|
sig_t action;
|
|
|
|
|
|
|
|
mtx_lock(&ps->ps_mtx);
|
|
|
|
action = ps->ps_sigact[_SIG_IDX(sig)];
|
|
|
|
mtx_unlock(&ps->ps_mtx);
|
2011-04-17 14:38:11 +00:00
|
|
|
ktrpsig(sig, action, &td->td_sigmask, ksi->ksi_code);
|
2006-02-23 09:24:19 +00:00
|
|
|
}
|
2003-03-31 23:30:41 +00:00
|
|
|
#endif
|
2017-03-30 18:21:36 +00:00
|
|
|
if (sig == SIGKILL) {
|
|
|
|
proc_td_siginfo_capture(td, &ksi->ksi_info);
|
2006-02-23 09:24:19 +00:00
|
|
|
sigexit(td, sig);
|
2017-03-30 18:21:36 +00:00
|
|
|
}
|
2003-07-17 22:52:55 +00:00
|
|
|
}
|
2003-03-31 23:30:41 +00:00
|
|
|
PROC_UNLOCK(p);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct sigpending_args {
|
|
|
|
sigset_t *set;
|
|
|
|
};
|
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
sys_sigpending(struct thread *td, struct sigpending_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2001-09-12 08:38:13 +00:00
|
|
|
struct proc *p = td->td_proc;
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sigset_t pending;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_LOCK(p);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
pending = p->p_sigqueue.sq_signals;
|
|
|
|
SIGSETOR(pending, td->td_sigqueue.sq_signals);
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_UNLOCK(p);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
return (copyout(&pending, uap->set, sizeof(sigset_t)));
|
1999-09-29 15:03:48 +00:00
|
|
|
}
|
|
|
|
|
2000-08-26 02:27:01 +00:00
|
|
|
#ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */
|
1999-09-29 15:03:48 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct osigpending_args {
|
|
|
|
int dummy;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
osigpending(struct thread *td, struct osigpending_args *uap)
|
1999-09-29 15:03:48 +00:00
|
|
|
{
|
2001-09-12 08:38:13 +00:00
|
|
|
struct proc *p = td->td_proc;
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sigset_t pending;
|
2001-09-12 08:38:13 +00:00
|
|
|
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_LOCK(p);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
pending = p->p_sigqueue.sq_signals;
|
|
|
|
SIGSETOR(pending, td->td_sigqueue.sq_signals);
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_UNLOCK(p);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
SIG2OSIG(pending, td->td_retval[0]);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (0);
|
|
|
|
}
|
2000-08-26 02:27:01 +00:00
|
|
|
#endif /* COMPAT_43 */
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2004-06-11 11:16:26 +00:00
|
|
|
#if defined(COMPAT_43)
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Generalized interface signal handler, 4.3-compatible.
|
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct osigvec_args {
|
|
|
|
int signum;
|
|
|
|
struct sigvec *nsv;
|
|
|
|
struct sigvec *osv;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
osigvec(struct thread *td, struct osigvec_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
struct sigvec vec;
|
1999-09-29 15:03:48 +00:00
|
|
|
struct sigaction nsa, osa;
|
2017-03-02 22:17:53 +00:00
|
|
|
struct sigaction *nsap, *osap;
|
1999-09-29 15:03:48 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1999-10-12 13:14:18 +00:00
|
|
|
if (uap->signum <= 0 || uap->signum >= ONSIG)
|
|
|
|
return (EINVAL);
|
|
|
|
nsap = (uap->nsv != NULL) ? &nsa : NULL;
|
|
|
|
osap = (uap->osv != NULL) ? &osa : NULL;
|
1999-09-29 15:03:48 +00:00
|
|
|
if (nsap) {
|
1999-10-12 13:14:18 +00:00
|
|
|
error = copyin(uap->nsv, &vec, sizeof(vec));
|
1999-09-29 15:03:48 +00:00
|
|
|
if (error)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (error);
|
1999-09-29 15:03:48 +00:00
|
|
|
nsap->sa_handler = vec.sv_handler;
|
|
|
|
OSIG2SIG(vec.sv_mask, nsap->sa_mask);
|
|
|
|
nsap->sa_flags = vec.sv_flags;
|
|
|
|
nsap->sa_flags ^= SA_RESTART; /* opposite of SV_INTERRUPT */
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2003-04-17 22:06:43 +00:00
|
|
|
error = kern_sigaction(td, uap->signum, nsap, osap, KSA_OSIGSET);
|
1999-09-29 15:03:48 +00:00
|
|
|
if (osap && !error) {
|
|
|
|
vec.sv_handler = osap->sa_handler;
|
|
|
|
SIG2OSIG(osap->sa_mask, vec.sv_mask);
|
|
|
|
vec.sv_flags = osap->sa_flags;
|
|
|
|
vec.sv_flags &= ~SA_NOCLDWAIT;
|
|
|
|
vec.sv_flags ^= SA_RESTART;
|
1999-10-12 13:14:18 +00:00
|
|
|
error = copyout(&vec, uap->osv, sizeof(vec));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
1999-09-29 15:03:48 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct osigblock_args {
|
|
|
|
int mask;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
osigblock(struct thread *td, struct osigblock_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2009-10-27 10:47:58 +00:00
|
|
|
sigset_t set, oset;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1999-09-29 15:03:48 +00:00
|
|
|
OSIG2SIG(uap->mask, set);
|
2009-10-27 10:47:58 +00:00
|
|
|
kern_sigprocmask(td, SIG_BLOCK, &set, &oset, 0);
|
|
|
|
SIG2OSIG(oset, td->td_retval[0]);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct osigsetmask_args {
|
|
|
|
int mask;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
osigsetmask(struct thread *td, struct osigsetmask_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2009-10-27 10:47:58 +00:00
|
|
|
sigset_t set, oset;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1999-09-29 15:03:48 +00:00
|
|
|
OSIG2SIG(uap->mask, set);
|
2009-10-27 10:47:58 +00:00
|
|
|
kern_sigprocmask(td, SIG_SETMASK, &set, &oset, 0);
|
|
|
|
SIG2OSIG(oset, td->td_retval[0]);
|
1994-05-24 10:09:53 +00:00
|
|
|
return (0);
|
|
|
|
}
|
2004-06-11 11:16:26 +00:00
|
|
|
#endif /* COMPAT_43 */
|
1994-05-24 10:09:53 +00:00
|
|
|
|
|
|
|
/*
|
2007-03-05 13:10:58 +00:00
|
|
|
* Suspend calling thread until signal, providing mask to be set in the
|
2012-11-27 10:11:54 +00:00
|
|
|
* meantime.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct sigsuspend_args {
|
1999-09-29 15:03:48 +00:00
|
|
|
const sigset_t *sigmask;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
sys_sigsuspend(struct thread *td, struct sigsuspend_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
1999-09-29 15:03:48 +00:00
|
|
|
sigset_t mask;
|
|
|
|
int error;
|
|
|
|
|
1999-10-12 13:14:18 +00:00
|
|
|
error = copyin(uap->sigmask, &mask, sizeof(mask));
|
1999-09-29 15:03:48 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2002-09-01 20:37:28 +00:00
|
|
|
return (kern_sigsuspend(td, mask));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_sigsuspend(struct thread *td, sigset_t mask)
|
|
|
|
{
|
|
|
|
struct proc *p = td->td_proc;
|
2009-10-27 10:42:24 +00:00
|
|
|
int has_sig, sig;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
|
|
|
/*
|
1999-10-11 20:33:17 +00:00
|
|
|
* When returning from sigsuspend, we want
|
1994-05-24 10:09:53 +00:00
|
|
|
* the old mask to be restored after the
|
|
|
|
* signal handler has finished. Thus, we
|
|
|
|
* save it here and mark the sigacts structure
|
|
|
|
* to indicate this.
|
|
|
|
*/
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_LOCK(p);
|
2009-10-27 10:42:24 +00:00
|
|
|
kern_sigprocmask(td, SIG_SETMASK, &mask, &td->td_oldsigmask,
|
|
|
|
SIGPROCMASK_PROC_LOCKED);
|
2003-06-09 17:38:32 +00:00
|
|
|
td->td_pflags |= TDP_OLDMASK;
|
2009-10-27 10:42:24 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Process signals now. Otherwise, we can get spurious wakeup
|
|
|
|
* due to signal entered process queue, but delivered to other
|
|
|
|
* thread. But sigsuspend should return only on signal
|
|
|
|
* delivery.
|
|
|
|
*/
|
Reorganize syscall entry and leave handling.
Extend struct sysvec with three new elements:
sv_fetch_syscall_args - the method to fetch syscall arguments from
usermode into struct syscall_args. The structure is machine-depended
(this might be reconsidered after all architectures are converted).
sv_set_syscall_retval - the method to set a return value for usermode
from the syscall. It is a generalization of
cpu_set_syscall_retval(9) to allow ABIs to override the way to set a
return value.
sv_syscallnames - the table of syscall names.
Use sv_set_syscall_retval in kern_sigsuspend() instead of hardcoding
the call to cpu_set_syscall_retval().
The new functions syscallenter(9) and syscallret(9) are provided that
use sv_*syscall* pointers and contain the common repeated code from
the syscall() implementations for the architecture-specific syscall
trap handlers.
Syscallenter() fetches arguments, calls syscall implementation from
ABI sysent table, and set up return frame. The end of syscall
bookkeeping is done by syscallret().
Take advantage of single place for MI syscall handling code and
implement ptrace_lwpinfo pl_flags PL_FLAG_SCE, PL_FLAG_SCX and
PL_FLAG_EXEC. The SCE and SCX flags notify the debugger that the
thread is stopped at syscall entry or return point respectively. The
EXEC flag augments SCX and notifies debugger that the process address
space was changed by one of exec(2)-family syscalls.
The i386, amd64, sparc64, sun4v, powerpc and ia64 syscall()s are
changed to use syscallenter()/syscallret(). MIPS and arm are not
converted and use the mostly unchanged syscall() implementation.
Reviewed by: jhb, marcel, marius, nwhitehorn, stas
Tested by: marcel (ia64), marius (sparc64), nwhitehorn (powerpc),
stas (mips)
MFC after: 1 month
2010-05-23 18:32:02 +00:00
|
|
|
(p->p_sysent->sv_set_syscall_retval)(td, EINTR);
|
2009-10-27 10:42:24 +00:00
|
|
|
for (has_sig = 0; !has_sig;) {
|
|
|
|
while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "pause",
|
|
|
|
0) == 0)
|
|
|
|
/* void */;
|
|
|
|
thread_suspend_check(0);
|
|
|
|
mtx_lock(&p->p_sigacts->ps_mtx);
|
2016-07-03 18:19:48 +00:00
|
|
|
while ((sig = cursig(td)) != 0) {
|
|
|
|
KASSERT(sig >= 0, ("sig %d", sig));
|
In r198506, kern_sigsuspend() started doing cursig/postsig loop to make
sure that a signal was delivered to the thread before returning from
syscall. Signal delivery puts new return frame on the user stack, and
modifies trap frame to enter signal handler. As a consequence, syscall
return code sets EINTR as error return for signal frame, instead of the
syscall return.
Also, for ia64, due to different registers layout for those two kind of
frames, usermode sigsegfaulted when returned from signal handler.
Use newly-introduced cpu_set_syscall_retval(9) to set syscall result,
and return EJUSTRETURN from kern_sigsuspend() to prevent syscall return
code from modifying this frame [1].
Another issue is that pending SIGCONT might be cancelled by SIGSTOP,
causing postsig() not to deliver any catched signal [2]. Modify
postsig() to return 1 if signal was posted, and 0 otherwise, and use
this in the kern_sigsuspend loop.
Proposed by: marcel [1]
Noted by: davidxu [2]
Reviewed by: marcel, davidxu
MFC after: 1 month
2009-11-10 11:46:53 +00:00
|
|
|
has_sig += postsig(sig);
|
2016-07-03 18:19:48 +00:00
|
|
|
}
|
2009-10-27 10:42:24 +00:00
|
|
|
mtx_unlock(&p->p_sigacts->ps_mtx);
|
2019-11-27 20:33:53 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If PTRACE_SCE or PTRACE_SCX were set after
|
|
|
|
* userspace entered the syscall, return spurious
|
|
|
|
* EINTR.
|
|
|
|
*/
|
|
|
|
if ((p->p_ptevents & PTRACE_SYSCALL) != 0)
|
|
|
|
has_sig += 1;
|
2009-10-27 10:42:24 +00:00
|
|
|
}
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_UNLOCK(p);
|
2012-04-12 10:48:43 +00:00
|
|
|
td->td_errno = EINTR;
|
|
|
|
td->td_pflags |= TDP_NERRNO;
|
In r198506, kern_sigsuspend() started doing cursig/postsig loop to make
sure that a signal was delivered to the thread before returning from
syscall. Signal delivery puts new return frame on the user stack, and
modifies trap frame to enter signal handler. As a consequence, syscall
return code sets EINTR as error return for signal frame, instead of the
syscall return.
Also, for ia64, due to different registers layout for those two kind of
frames, usermode sigsegfaulted when returned from signal handler.
Use newly-introduced cpu_set_syscall_retval(9) to set syscall result,
and return EJUSTRETURN from kern_sigsuspend() to prevent syscall return
code from modifying this frame [1].
Another issue is that pending SIGCONT might be cancelled by SIGSTOP,
causing postsig() not to deliver any catched signal [2]. Modify
postsig() to return 1 if signal was posted, and 0 otherwise, and use
this in the kern_sigsuspend loop.
Proposed by: marcel [1]
Noted by: davidxu [2]
Reviewed by: marcel, davidxu
MFC after: 1 month
2009-11-10 11:46:53 +00:00
|
|
|
return (EJUSTRETURN);
|
1999-09-29 15:03:48 +00:00
|
|
|
}
|
|
|
|
|
2000-08-26 02:27:01 +00:00
|
|
|
#ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */
|
2004-01-28 06:06:04 +00:00
|
|
|
/*
|
|
|
|
* Compatibility sigsuspend call for old binaries. Note nonstandard calling
|
|
|
|
* convention: libc stub passes mask, not pointer, to save a copyin.
|
|
|
|
*/
|
1999-09-29 15:03:48 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct osigsuspend_args {
|
|
|
|
osigset_t mask;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
/* ARGSUSED */
|
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
osigsuspend(struct thread *td, struct osigsuspend_args *uap)
|
1999-09-29 15:03:48 +00:00
|
|
|
{
|
1999-10-11 20:33:17 +00:00
|
|
|
sigset_t mask;
|
1999-09-29 15:03:48 +00:00
|
|
|
|
1999-10-11 20:33:17 +00:00
|
|
|
OSIG2SIG(uap->mask, mask);
|
2009-10-27 10:42:24 +00:00
|
|
|
return (kern_sigsuspend(td, mask));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2000-08-26 02:27:01 +00:00
|
|
|
#endif /* COMPAT_43 */
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2004-06-11 11:16:26 +00:00
|
|
|
#if defined(COMPAT_43)
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct osigstack_args {
|
|
|
|
struct sigstack *nss;
|
|
|
|
struct sigstack *oss;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
osigstack(struct thread *td, struct osigstack_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2003-04-23 18:50:25 +00:00
|
|
|
struct sigstack nss, oss;
|
2001-09-01 18:19:21 +00:00
|
|
|
int error = 0;
|
|
|
|
|
2003-04-23 18:50:25 +00:00
|
|
|
if (uap->nss != NULL) {
|
|
|
|
error = copyin(uap->nss, &nss, sizeof(nss));
|
2000-11-30 05:23:49 +00:00
|
|
|
if (error)
|
2003-04-23 18:50:25 +00:00
|
|
|
return (error);
|
2000-11-30 05:23:49 +00:00
|
|
|
}
|
2004-01-03 02:02:26 +00:00
|
|
|
oss.ss_sp = td->td_sigstk.ss_sp;
|
2003-04-23 18:50:25 +00:00
|
|
|
oss.ss_onstack = sigonstack(cpu_getstack(td));
|
2000-11-30 05:23:49 +00:00
|
|
|
if (uap->nss != NULL) {
|
2004-01-03 02:02:26 +00:00
|
|
|
td->td_sigstk.ss_sp = nss.ss_sp;
|
|
|
|
td->td_sigstk.ss_size = 0;
|
|
|
|
td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK;
|
|
|
|
td->td_pflags |= TDP_ALTSTACK;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2003-04-23 18:50:25 +00:00
|
|
|
if (uap->oss != NULL)
|
|
|
|
error = copyout(&oss, uap->oss, sizeof(oss));
|
|
|
|
|
2001-09-01 18:19:21 +00:00
|
|
|
return (error);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2004-06-11 11:16:26 +00:00
|
|
|
#endif /* COMPAT_43 */
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct sigaltstack_args {
|
1999-09-29 15:03:48 +00:00
|
|
|
stack_t *ss;
|
|
|
|
stack_t *oss;
|
1994-05-24 10:09:53 +00:00
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
sys_sigaltstack(struct thread *td, struct sigaltstack_args *uap)
|
2002-09-01 20:37:28 +00:00
|
|
|
{
|
|
|
|
stack_t ss, oss;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (uap->ss != NULL) {
|
|
|
|
error = copyin(uap->ss, &ss, sizeof(ss));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
error = kern_sigaltstack(td, (uap->ss != NULL) ? &ss : NULL,
|
|
|
|
(uap->oss != NULL) ? &oss : NULL);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
if (uap->oss != NULL)
|
|
|
|
error = copyout(&oss, uap->oss, sizeof(stack_t));
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_sigaltstack(struct thread *td, stack_t *ss, stack_t *oss)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2001-09-12 08:38:13 +00:00
|
|
|
struct proc *p = td->td_proc;
|
2001-09-01 18:19:21 +00:00
|
|
|
int oonstack;
|
|
|
|
|
2001-09-12 08:38:13 +00:00
|
|
|
oonstack = sigonstack(cpu_getstack(td));
|
2000-11-30 05:23:49 +00:00
|
|
|
|
2002-09-01 20:37:28 +00:00
|
|
|
if (oss != NULL) {
|
2004-01-03 02:02:26 +00:00
|
|
|
*oss = td->td_sigstk;
|
|
|
|
oss->ss_flags = (td->td_pflags & TDP_ALTSTACK)
|
2000-11-30 05:23:49 +00:00
|
|
|
? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
|
|
|
|
}
|
|
|
|
|
2002-09-01 20:37:28 +00:00
|
|
|
if (ss != NULL) {
|
2004-01-03 02:02:26 +00:00
|
|
|
if (oonstack)
|
2003-04-23 19:49:18 +00:00
|
|
|
return (EPERM);
|
2004-01-03 02:02:26 +00:00
|
|
|
if ((ss->ss_flags & ~SS_DISABLE) != 0)
|
2003-04-23 19:49:18 +00:00
|
|
|
return (EINVAL);
|
2002-09-01 20:37:28 +00:00
|
|
|
if (!(ss->ss_flags & SS_DISABLE)) {
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
if (ss->ss_size < p->p_sysent->sv_minsigstksz)
|
2003-04-23 19:49:18 +00:00
|
|
|
return (ENOMEM);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
|
2004-01-03 02:02:26 +00:00
|
|
|
td->td_sigstk = *ss;
|
|
|
|
td->td_pflags |= TDP_ALTSTACK;
|
2001-03-07 02:59:54 +00:00
|
|
|
} else {
|
2004-01-03 02:02:26 +00:00
|
|
|
td->td_pflags &= ~TDP_ALTSTACK;
|
2001-03-07 02:59:54 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2003-04-23 19:49:18 +00:00
|
|
|
return (0);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2019-12-07 18:07:49 +00:00
|
|
|
struct killpg1_ctx {
|
|
|
|
struct thread *td;
|
|
|
|
ksiginfo_t *ksi;
|
|
|
|
int sig;
|
|
|
|
bool sent;
|
|
|
|
bool found;
|
|
|
|
int ret;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
killpg1_sendsig(struct proc *p, bool notself, struct killpg1_ctx *arg)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (p->p_pid <= 1 || (p->p_flag & P_SYSTEM) != 0 ||
|
|
|
|
(notself && p == arg->td->td_proc) || p->p_state == PRS_NEW)
|
|
|
|
return;
|
|
|
|
PROC_LOCK(p);
|
|
|
|
err = p_cansignal(arg->td, p, arg->sig);
|
|
|
|
if (err == 0 && arg->sig != 0)
|
|
|
|
pksignal(p, arg->sig, arg->ksi);
|
|
|
|
PROC_UNLOCK(p);
|
|
|
|
if (err != ESRCH)
|
|
|
|
arg->found = true;
|
|
|
|
if (err == 0)
|
|
|
|
arg->sent = true;
|
|
|
|
else if (arg->ret == 0 && err != ESRCH && err != EPERM)
|
|
|
|
arg->ret = err;
|
|
|
|
}
|
|
|
|
|
1994-10-10 01:00:49 +00:00
|
|
|
/*
|
|
|
|
* Common code for kill process group/broadcast kill.
|
|
|
|
* cp is calling process.
|
|
|
|
*/
|
2002-09-28 17:15:38 +00:00
|
|
|
static int
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
killpg1(struct thread *td, int sig, int pgid, int all, ksiginfo_t *ksi)
|
1994-10-10 01:00:49 +00:00
|
|
|
{
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
struct proc *p;
|
1994-10-10 01:00:49 +00:00
|
|
|
struct pgrp *pgrp;
|
2019-12-07 18:07:49 +00:00
|
|
|
struct killpg1_ctx arg;
|
|
|
|
|
|
|
|
arg.td = td;
|
|
|
|
arg.ksi = ksi;
|
|
|
|
arg.sig = sig;
|
|
|
|
arg.sent = false;
|
|
|
|
arg.found = false;
|
|
|
|
arg.ret = 0;
|
2000-11-22 07:42:04 +00:00
|
|
|
if (all) {
|
1995-05-30 08:16:23 +00:00
|
|
|
/*
|
|
|
|
* broadcast
|
1994-10-10 01:00:49 +00:00
|
|
|
*/
|
2001-03-28 11:52:56 +00:00
|
|
|
sx_slock(&allproc_lock);
|
2007-01-17 14:58:53 +00:00
|
|
|
FOREACH_PROC_IN_SYSTEM(p) {
|
2019-12-07 18:07:49 +00:00
|
|
|
killpg1_sendsig(p, true, &arg);
|
1994-10-10 01:00:49 +00:00
|
|
|
}
|
2001-03-28 11:52:56 +00:00
|
|
|
sx_sunlock(&allproc_lock);
|
2000-11-22 07:42:04 +00:00
|
|
|
} else {
|
2002-04-16 17:11:34 +00:00
|
|
|
sx_slock(&proctree_lock);
|
2002-02-23 11:12:57 +00:00
|
|
|
if (pgid == 0) {
|
1995-05-30 08:16:23 +00:00
|
|
|
/*
|
1994-10-10 01:00:49 +00:00
|
|
|
* zero pgid means send to my process group.
|
|
|
|
*/
|
2002-04-13 23:33:36 +00:00
|
|
|
pgrp = td->td_proc->p_pgrp;
|
2002-02-23 11:12:57 +00:00
|
|
|
PGRP_LOCK(pgrp);
|
|
|
|
} else {
|
1994-10-10 01:00:49 +00:00
|
|
|
pgrp = pgfind(pgid);
|
2002-02-23 11:12:57 +00:00
|
|
|
if (pgrp == NULL) {
|
2002-04-16 17:11:34 +00:00
|
|
|
sx_sunlock(&proctree_lock);
|
1994-10-10 01:00:49 +00:00
|
|
|
return (ESRCH);
|
2002-02-23 11:12:57 +00:00
|
|
|
}
|
1994-10-10 01:00:49 +00:00
|
|
|
}
|
2002-04-16 17:11:34 +00:00
|
|
|
sx_sunlock(&proctree_lock);
|
1999-11-16 10:56:05 +00:00
|
|
|
LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
|
2019-12-07 18:07:49 +00:00
|
|
|
killpg1_sendsig(p, false, &arg);
|
1994-10-10 01:00:49 +00:00
|
|
|
}
|
2002-02-23 11:12:57 +00:00
|
|
|
PGRP_UNLOCK(pgrp);
|
1994-10-10 01:00:49 +00:00
|
|
|
}
|
2019-12-07 18:07:49 +00:00
|
|
|
MPASS(arg.ret != 0 || arg.found || !arg.sent);
|
|
|
|
if (arg.ret == 0 && !arg.sent)
|
|
|
|
arg.ret = arg.found ? EPERM : ESRCH;
|
|
|
|
return (arg.ret);
|
1994-10-10 01:00:49 +00:00
|
|
|
}
|
|
|
|
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct kill_args {
|
|
|
|
int pid;
|
|
|
|
int signum;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_kill(struct thread *td, struct kill_args *uap)
|
2019-12-13 18:44:02 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_kill(td, uap->pid, uap->signum));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_kill(struct thread *td, pid_t pid, int signum)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
ksiginfo_t ksi;
|
|
|
|
struct proc *p;
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
int error;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2012-11-27 10:22:40 +00:00
|
|
|
/*
|
|
|
|
* A process in capability mode can send signals only to himself.
|
|
|
|
* The main rationale behind this is that abort(3) is implemented as
|
|
|
|
* kill(getpid(), SIGABRT).
|
|
|
|
*/
|
2019-12-13 18:44:02 +00:00
|
|
|
if (IN_CAPABILITY_MODE(td) && pid != td->td_proc->p_pid)
|
2012-11-27 10:22:40 +00:00
|
|
|
return (ECAPMODE);
|
|
|
|
|
2019-12-13 18:44:02 +00:00
|
|
|
AUDIT_ARG_SIGNUM(signum);
|
|
|
|
AUDIT_ARG_PID(pid);
|
|
|
|
if ((u_int)signum > _SIG_MAXSIG)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (EINVAL);
|
2001-09-01 18:19:21 +00:00
|
|
|
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
ksiginfo_init(&ksi);
|
2019-12-13 18:44:02 +00:00
|
|
|
ksi.ksi_signo = signum;
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
ksi.ksi_code = SI_USER;
|
|
|
|
ksi.ksi_pid = td->td_proc->p_pid;
|
|
|
|
ksi.ksi_uid = td->td_ucred->cr_ruid;
|
|
|
|
|
2019-12-13 18:44:02 +00:00
|
|
|
if (pid > 0) {
|
1994-05-24 10:09:53 +00:00
|
|
|
/* kill single process */
|
2019-12-13 18:44:02 +00:00
|
|
|
if ((p = pfind_any(pid)) == NULL)
|
2017-11-11 18:04:39 +00:00
|
|
|
return (ESRCH);
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_PROCESS(p);
|
2019-12-13 18:44:02 +00:00
|
|
|
error = p_cansignal(td, p, signum);
|
|
|
|
if (error == 0 && signum)
|
|
|
|
pksignal(p, signum, &ksi);
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
PROC_UNLOCK(p);
|
|
|
|
return (error);
|
|
|
|
}
|
2019-12-13 18:44:02 +00:00
|
|
|
switch (pid) {
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
case -1: /* broadcast signal */
|
2019-12-13 18:44:02 +00:00
|
|
|
return (killpg1(td, signum, 0, 1, &ksi));
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
case 0: /* signal own process group */
|
2019-12-13 18:44:02 +00:00
|
|
|
return (killpg1(td, signum, 0, 0, &ksi));
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
default: /* negative explicit process group */
|
2019-12-13 18:44:02 +00:00
|
|
|
return (killpg1(td, signum, -pid, 0, &ksi));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
/* NOTREACHED */
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
Add experimental support for process descriptors
A "process descriptor" file descriptor is used to manage processes
without using the PID namespace. This is required for Capsicum's
Capability Mode, where the PID namespace is unavailable.
New system calls pdfork(2) and pdkill(2) offer the functional equivalents
of fork(2) and kill(2). pdgetpid(2) allows querying the PID of the remote
process for debugging purposes. The currently-unimplemented pdwait(2) will,
in the future, allow querying rusage/exit status. In the interim, poll(2)
may be used to check (and wait for) process termination.
When a process is referenced by a process descriptor, it does not issue
SIGCHLD to the parent, making it suitable for use in libraries---a common
scenario when using library compartmentalisation from within large
applications (such as web browsers). Some observers may note a similarity
to Mach task ports; process descriptors provide a subset of this behaviour,
but in a UNIX style.
This feature is enabled by "options PROCDESC", but as with several other
Capsicum kernel features, is not enabled by default in GENERIC 9.0.
Reviewed by: jhb, kib
Approved by: re (kib), mentor (rwatson)
Sponsored by: Google Inc
2011-08-18 22:51:30 +00:00
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
sys_pdkill(struct thread *td, struct pdkill_args *uap)
|
Add experimental support for process descriptors
A "process descriptor" file descriptor is used to manage processes
without using the PID namespace. This is required for Capsicum's
Capability Mode, where the PID namespace is unavailable.
New system calls pdfork(2) and pdkill(2) offer the functional equivalents
of fork(2) and kill(2). pdgetpid(2) allows querying the PID of the remote
process for debugging purposes. The currently-unimplemented pdwait(2) will,
in the future, allow querying rusage/exit status. In the interim, poll(2)
may be used to check (and wait for) process termination.
When a process is referenced by a process descriptor, it does not issue
SIGCHLD to the parent, making it suitable for use in libraries---a common
scenario when using library compartmentalisation from within large
applications (such as web browsers). Some observers may note a similarity
to Mach task ports; process descriptors provide a subset of this behaviour,
but in a UNIX style.
This feature is enabled by "options PROCDESC", but as with several other
Capsicum kernel features, is not enabled by default in GENERIC 9.0.
Reviewed by: jhb, kib
Approved by: re (kib), mentor (rwatson)
Sponsored by: Google Inc
2011-08-18 22:51:30 +00:00
|
|
|
{
|
|
|
|
struct proc *p;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
AUDIT_ARG_SIGNUM(uap->signum);
|
|
|
|
AUDIT_ARG_FD(uap->fd);
|
|
|
|
if ((u_int)uap->signum > _SIG_MAXSIG)
|
|
|
|
return (EINVAL);
|
|
|
|
|
2018-05-09 18:47:24 +00:00
|
|
|
error = procdesc_find(td, uap->fd, &cap_pdkill_rights, &p);
|
Add experimental support for process descriptors
A "process descriptor" file descriptor is used to manage processes
without using the PID namespace. This is required for Capsicum's
Capability Mode, where the PID namespace is unavailable.
New system calls pdfork(2) and pdkill(2) offer the functional equivalents
of fork(2) and kill(2). pdgetpid(2) allows querying the PID of the remote
process for debugging purposes. The currently-unimplemented pdwait(2) will,
in the future, allow querying rusage/exit status. In the interim, poll(2)
may be used to check (and wait for) process termination.
When a process is referenced by a process descriptor, it does not issue
SIGCHLD to the parent, making it suitable for use in libraries---a common
scenario when using library compartmentalisation from within large
applications (such as web browsers). Some observers may note a similarity
to Mach task ports; process descriptors provide a subset of this behaviour,
but in a UNIX style.
This feature is enabled by "options PROCDESC", but as with several other
Capsicum kernel features, is not enabled by default in GENERIC 9.0.
Reviewed by: jhb, kib
Approved by: re (kib), mentor (rwatson)
Sponsored by: Google Inc
2011-08-18 22:51:30 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
AUDIT_ARG_PROCESS(p);
|
|
|
|
error = p_cansignal(td, p, uap->signum);
|
|
|
|
if (error == 0 && uap->signum)
|
2011-09-16 13:58:51 +00:00
|
|
|
kern_psignal(p, uap->signum);
|
Add experimental support for process descriptors
A "process descriptor" file descriptor is used to manage processes
without using the PID namespace. This is required for Capsicum's
Capability Mode, where the PID namespace is unavailable.
New system calls pdfork(2) and pdkill(2) offer the functional equivalents
of fork(2) and kill(2). pdgetpid(2) allows querying the PID of the remote
process for debugging purposes. The currently-unimplemented pdwait(2) will,
in the future, allow querying rusage/exit status. In the interim, poll(2)
may be used to check (and wait for) process termination.
When a process is referenced by a process descriptor, it does not issue
SIGCHLD to the parent, making it suitable for use in libraries---a common
scenario when using library compartmentalisation from within large
applications (such as web browsers). Some observers may note a similarity
to Mach task ports; process descriptors provide a subset of this behaviour,
but in a UNIX style.
This feature is enabled by "options PROCDESC", but as with several other
Capsicum kernel features, is not enabled by default in GENERIC 9.0.
Reviewed by: jhb, kib
Approved by: re (kib), mentor (rwatson)
Sponsored by: Google Inc
2011-08-18 22:51:30 +00:00
|
|
|
PROC_UNLOCK(p);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2004-06-11 11:16:26 +00:00
|
|
|
#if defined(COMPAT_43)
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct okillpg_args {
|
|
|
|
int pgid;
|
|
|
|
int signum;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
okillpg(struct thread *td, struct okillpg_args *uap)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
ksiginfo_t ksi;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2009-06-27 13:58:44 +00:00
|
|
|
AUDIT_ARG_SIGNUM(uap->signum);
|
|
|
|
AUDIT_ARG_PID(uap->pgid);
|
2001-11-03 13:26:15 +00:00
|
|
|
if ((u_int)uap->signum > _SIG_MAXSIG)
|
1994-05-24 10:09:53 +00:00
|
|
|
return (EINVAL);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
ksiginfo_init(&ksi);
|
|
|
|
ksi.ksi_signo = uap->signum;
|
|
|
|
ksi.ksi_code = SI_USER;
|
|
|
|
ksi.ksi_pid = td->td_proc->p_pid;
|
|
|
|
ksi.ksi_uid = td->td_ucred->cr_ruid;
|
|
|
|
return (killpg1(td, uap->signum, uap->pgid, 0, &ksi));
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2004-06-11 11:16:26 +00:00
|
|
|
#endif /* COMPAT_43 */
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct sigqueue_args {
|
|
|
|
pid_t pid;
|
|
|
|
int signum;
|
|
|
|
/* union sigval */ void *value;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_sigqueue(struct thread *td, struct sigqueue_args *uap)
|
2017-05-05 18:49:39 +00:00
|
|
|
{
|
|
|
|
union sigval sv;
|
|
|
|
|
|
|
|
sv.sival_ptr = uap->value;
|
|
|
|
|
|
|
|
return (kern_sigqueue(td, uap->pid, uap->signum, &sv));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_sigqueue(struct thread *td, pid_t pid, int signum, union sigval *value)
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
{
|
|
|
|
ksiginfo_t ksi;
|
|
|
|
struct proc *p;
|
|
|
|
int error;
|
|
|
|
|
2017-05-05 18:49:39 +00:00
|
|
|
if ((u_int)signum > _SIG_MAXSIG)
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Specification says sigqueue can only send signal to
|
|
|
|
* single process.
|
|
|
|
*/
|
2017-05-05 18:49:39 +00:00
|
|
|
if (pid <= 0)
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
return (EINVAL);
|
|
|
|
|
2017-11-11 18:10:09 +00:00
|
|
|
if ((p = pfind_any(pid)) == NULL)
|
|
|
|
return (ESRCH);
|
2017-05-05 18:49:39 +00:00
|
|
|
error = p_cansignal(td, p, signum);
|
|
|
|
if (error == 0 && signum != 0) {
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
ksiginfo_init(&ksi);
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
ksi.ksi_flags = KSI_SIGQ;
|
2017-05-05 18:49:39 +00:00
|
|
|
ksi.ksi_signo = signum;
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
ksi.ksi_code = SI_QUEUE;
|
|
|
|
ksi.ksi_pid = td->td_proc->p_pid;
|
|
|
|
ksi.ksi_uid = td->td_ucred->cr_ruid;
|
2017-05-05 18:49:39 +00:00
|
|
|
ksi.ksi_value = *value;
|
2010-06-29 20:41:52 +00:00
|
|
|
error = pksignal(p, ksi.ksi_signo, &ksi);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
}
|
|
|
|
PROC_UNLOCK(p);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Send a signal to a process group.
|
|
|
|
*/
|
|
|
|
void
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
gsignal(int pgid, int sig, ksiginfo_t *ksi)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
|
|
|
struct pgrp *pgrp;
|
|
|
|
|
2002-02-23 11:12:57 +00:00
|
|
|
if (pgid != 0) {
|
2002-04-16 17:11:34 +00:00
|
|
|
sx_slock(&proctree_lock);
|
2002-02-23 11:12:57 +00:00
|
|
|
pgrp = pgfind(pgid);
|
2002-04-16 17:11:34 +00:00
|
|
|
sx_sunlock(&proctree_lock);
|
2002-02-23 11:12:57 +00:00
|
|
|
if (pgrp != NULL) {
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
pgsignal(pgrp, sig, 0, ksi);
|
2002-02-23 11:12:57 +00:00
|
|
|
PGRP_UNLOCK(pgrp);
|
|
|
|
}
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-02-10 02:22:35 +00:00
|
|
|
* Send a signal to a process group. If checktty is 1,
|
1994-05-24 10:09:53 +00:00
|
|
|
* limit to members which have a controlling terminal.
|
|
|
|
*/
|
|
|
|
void
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
pgsignal(struct pgrp *pgrp, int sig, int checkctty, ksiginfo_t *ksi)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
struct proc *p;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2001-03-07 02:59:54 +00:00
|
|
|
if (pgrp) {
|
2002-02-23 11:12:57 +00:00
|
|
|
PGRP_LOCK_ASSERT(pgrp, MA_OWNED);
|
2001-03-07 02:59:54 +00:00
|
|
|
LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
|
|
|
|
PROC_LOCK(p);
|
2011-04-06 17:47:22 +00:00
|
|
|
if (p->p_state == PRS_NORMAL &&
|
|
|
|
(checkctty == 0 || p->p_flag & P_CONTROLT))
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
pksignal(p, sig, ksi);
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_UNLOCK(p);
|
|
|
|
}
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2014-11-26 14:09:04 +00:00
|
|
|
/*
|
|
|
|
* Recalculate the signal mask and reset the signal disposition after
|
|
|
|
* usermode frame for delivery is formed. Should be called after
|
|
|
|
* mach-specific routine, because sysent->sv_sendsig() needs correct
|
|
|
|
* ps_siginfo and signal mask.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
postsig_done(int sig, struct thread *td, struct sigacts *ps)
|
|
|
|
{
|
|
|
|
sigset_t mask;
|
|
|
|
|
|
|
|
mtx_assert(&ps->ps_mtx, MA_OWNED);
|
|
|
|
td->td_ru.ru_nsignals++;
|
|
|
|
mask = ps->ps_catchmask[_SIG_IDX(sig)];
|
|
|
|
if (!SIGISMEMBER(ps->ps_signodefer, sig))
|
|
|
|
SIGADDSET(mask, sig);
|
|
|
|
kern_sigprocmask(td, SIG_BLOCK, &mask, NULL,
|
|
|
|
SIGPROCMASK_PROC_LOCKED | SIGPROCMASK_PS_LOCKED);
|
|
|
|
if (SIGISMEMBER(ps->ps_sigreset, sig))
|
|
|
|
sigdflt(ps, sig);
|
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2007-03-04 22:36:48 +00:00
|
|
|
* Send a signal caused by a trap to the current thread. If it will be
|
|
|
|
* caught immediately, deliver it with correct code. Otherwise, post it
|
|
|
|
* normally.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
|
|
|
void
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
trapsignal(struct thread *td, ksiginfo_t *ksi)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2003-03-31 22:02:38 +00:00
|
|
|
struct sigacts *ps;
|
|
|
|
struct proc *p;
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
sigset_t sigmask;
|
|
|
|
int code, sig;
|
2003-03-31 22:02:38 +00:00
|
|
|
|
|
|
|
p = td->td_proc;
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sig = ksi->ksi_signo;
|
|
|
|
code = ksi->ksi_code;
|
|
|
|
KASSERT(_SIG_VALID(sig), ("invalid signal"));
|
|
|
|
|
2020-02-20 15:34:02 +00:00
|
|
|
sigfastblock_fetch(td);
|
2006-10-26 21:42:22 +00:00
|
|
|
PROC_LOCK(p);
|
2003-03-09 01:40:55 +00:00
|
|
|
ps = p->p_sigacts;
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_lock(&ps->ps_mtx);
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
sigmask = td->td_sigmask;
|
|
|
|
if (td->td_sigblock_val != 0)
|
|
|
|
SIGSETOR(sigmask, fastblock_mask);
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
if ((p->p_flag & P_TRACED) == 0 && SIGISMEMBER(ps->ps_sigcatch, sig) &&
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
!SIGISMEMBER(sigmask, sig)) {
|
1994-05-24 10:09:53 +00:00
|
|
|
#ifdef KTRACE
|
2002-06-07 05:43:02 +00:00
|
|
|
if (KTRPOINT(curthread, KTR_PSIG))
|
|
|
|
ktrpsig(sig, ps->ps_sigact[_SIG_IDX(sig)],
|
2003-03-31 22:49:17 +00:00
|
|
|
&td->td_sigmask, code);
|
1994-05-24 10:09:53 +00:00
|
|
|
#endif
|
2012-11-27 10:11:54 +00:00
|
|
|
(*p->p_sysent->sv_sendsig)(ps->ps_sigact[_SIG_IDX(sig)],
|
2006-10-26 21:42:22 +00:00
|
|
|
ksi, &td->td_sigmask);
|
2014-11-26 14:09:04 +00:00
|
|
|
postsig_done(sig, td, ps);
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_unlock(&ps->ps_mtx);
|
1999-10-12 13:14:18 +00:00
|
|
|
} else {
|
2005-12-09 08:29:29 +00:00
|
|
|
/*
|
|
|
|
* Avoid a possible infinite loop if the thread
|
|
|
|
* masking the signal or process is ignoring the
|
|
|
|
* signal.
|
|
|
|
*/
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
if (kern_forcesigexit && (SIGISMEMBER(sigmask, sig) ||
|
|
|
|
ps->ps_sigact[_SIG_IDX(sig)] == SIG_IGN)) {
|
2005-12-09 08:29:29 +00:00
|
|
|
SIGDELSET(td->td_sigmask, sig);
|
|
|
|
SIGDELSET(ps->ps_sigcatch, sig);
|
|
|
|
SIGDELSET(ps->ps_sigignore, sig);
|
|
|
|
ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL;
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
td->td_pflags &= ~TDP_SIGFASTBLOCK;
|
|
|
|
td->td_sigblock_val = 0;
|
2005-12-09 08:29:29 +00:00
|
|
|
}
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_unlock(&ps->ps_mtx);
|
1999-09-29 15:03:48 +00:00
|
|
|
p->p_sig = sig; /* XXX to verify code */
|
2010-06-29 20:41:52 +00:00
|
|
|
tdsendsignal(p, td, sig, ksi);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_UNLOCK(p);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2003-03-31 22:49:17 +00:00
|
|
|
static struct thread *
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
sigtd(struct proc *p, int sig, bool fast_sigblock)
|
2003-03-31 22:49:17 +00:00
|
|
|
{
|
2003-07-17 22:52:55 +00:00
|
|
|
struct thread *td, *signal_td;
|
2003-03-31 22:49:17 +00:00
|
|
|
|
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
MPASS(!fast_sigblock || p == curproc);
|
2003-03-31 22:49:17 +00:00
|
|
|
|
|
|
|
/*
|
2005-03-04 22:46:31 +00:00
|
|
|
* Check if current thread can handle the signal without
|
2009-10-01 12:46:58 +00:00
|
|
|
* switching context to another thread.
|
2003-03-31 22:49:17 +00:00
|
|
|
*/
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
if (curproc == p && !SIGISMEMBER(curthread->td_sigmask, sig) &&
|
|
|
|
(!fast_sigblock || curthread->td_sigblock_val == 0))
|
2005-03-04 22:46:31 +00:00
|
|
|
return (curthread);
|
2003-07-17 22:52:55 +00:00
|
|
|
signal_td = NULL;
|
|
|
|
FOREACH_THREAD_IN_PROC(p, td) {
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
if (!SIGISMEMBER(td->td_sigmask, sig) && (!fast_sigblock ||
|
|
|
|
td != curthread || td->td_sigblock_val == 0)) {
|
2005-03-04 22:46:31 +00:00
|
|
|
signal_td = td;
|
|
|
|
break;
|
2003-07-17 22:52:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (signal_td == NULL)
|
|
|
|
signal_td = FIRST_THREAD_IN_PROC(p);
|
|
|
|
return (signal_td);
|
2003-03-31 22:49:17 +00:00
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Send the signal to the process. If the signal has an action, the action
|
|
|
|
* is usually performed by the target process rather than the caller; we add
|
|
|
|
* the signal to the set of pending signals for the process.
|
|
|
|
*
|
|
|
|
* Exceptions:
|
|
|
|
* o When a stop signal is sent to a sleeping process that takes the
|
|
|
|
* default action, the process is stopped without awakening it.
|
|
|
|
* o SIGCONT restarts stopped processes (or puts them back to sleep)
|
|
|
|
* regardless of the signal action (eg, blocked or ignored).
|
|
|
|
*
|
|
|
|
* Other ignored signals are discarded immediately.
|
2012-11-27 10:11:54 +00:00
|
|
|
*
|
2007-05-23 17:27:42 +00:00
|
|
|
* NB: This function may be entered from the debugger via the "kill" DDB
|
|
|
|
* command. There is little that can be done to mitigate the possibly messy
|
|
|
|
* side effects of this unwise possibility.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
|
|
|
void
|
2011-09-16 13:58:51 +00:00
|
|
|
kern_psignal(struct proc *p, int sig)
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
{
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
ksiginfo_t ksi;
|
|
|
|
|
|
|
|
ksiginfo_init(&ksi);
|
|
|
|
ksi.ksi_signo = sig;
|
|
|
|
ksi.ksi_code = SI_KERNEL;
|
2010-06-29 20:41:52 +00:00
|
|
|
(void) tdsendsignal(p, NULL, sig, &ksi);
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
}
|
|
|
|
|
2010-06-29 20:41:52 +00:00
|
|
|
int
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
pksignal(struct proc *p, int sig, ksiginfo_t *ksi)
|
|
|
|
{
|
|
|
|
|
2010-06-29 20:41:52 +00:00
|
|
|
return (tdsendsignal(p, NULL, sig, ksi));
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
}
|
|
|
|
|
2010-10-09 02:50:23 +00:00
|
|
|
/* Utility function for finding a thread to send signal event to. */
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
int
|
2010-10-09 02:50:23 +00:00
|
|
|
sigev_findtd(struct proc *p ,struct sigevent *sigev, struct thread **ttd)
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
{
|
2010-10-09 02:50:23 +00:00
|
|
|
struct thread *td;
|
2003-03-31 22:49:17 +00:00
|
|
|
|
2005-11-03 04:49:16 +00:00
|
|
|
if (sigev->sigev_notify == SIGEV_THREAD_ID) {
|
2010-10-09 02:50:23 +00:00
|
|
|
td = tdfind(sigev->sigev_notify_thread_id, p->p_pid);
|
2005-11-03 04:49:16 +00:00
|
|
|
if (td == NULL)
|
|
|
|
return (ESRCH);
|
2010-10-09 02:50:23 +00:00
|
|
|
*ttd = td;
|
|
|
|
} else {
|
|
|
|
*ttd = NULL;
|
|
|
|
PROC_LOCK(p);
|
2005-11-03 04:49:16 +00:00
|
|
|
}
|
2010-10-09 02:50:23 +00:00
|
|
|
return (0);
|
2003-03-31 22:49:17 +00:00
|
|
|
}
|
|
|
|
|
2010-06-29 20:41:52 +00:00
|
|
|
void
|
|
|
|
tdsignal(struct thread *td, int sig)
|
|
|
|
{
|
|
|
|
ksiginfo_t ksi;
|
|
|
|
|
|
|
|
ksiginfo_init(&ksi);
|
|
|
|
ksi.ksi_signo = sig;
|
|
|
|
ksi.ksi_code = SI_KERNEL;
|
|
|
|
(void) tdsendsignal(td->td_proc, td, sig, &ksi);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
tdksignal(struct thread *td, int sig, ksiginfo_t *ksi)
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) tdsendsignal(td->td_proc, td, sig, ksi);
|
|
|
|
}
|
|
|
|
|
2010-10-09 02:50:23 +00:00
|
|
|
int
|
2010-06-29 20:41:52 +00:00
|
|
|
tdsendsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
|
o Change kse_thr_interrupt to allow send a signal to a specified thread,
or unblock a thread in kernel, and allow UTS to specify whether syscall
should be restarted.
o Add ability for UTS to monitor signal comes in and removed from process,
the flag PS_SIGEVENT is used to indicate the events.
o Add a KMF_WAITSIGEVENT for KSE mailbox flag, UTS call kse_release with
this flag set to wait for above signal event.
o For SA based thread, kernel masks all signal in its signal mask, let
UTS to use kse_thr_interrupt interrupt a thread, and install a signal
frame in userland for the thread.
o Add a tm_syncsig in thread mailbox, when a hardware trap occurs,
it is used to deliver synchronous signal to userland, and upcall
is schedule, so UTS can process the synchronous signal for the thread.
Reviewed by: julian (mentor)
2003-06-28 08:29:05 +00:00
|
|
|
{
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sig_t action;
|
|
|
|
sigqueue_t *sigqueue;
|
|
|
|
int prop;
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
struct sigacts *ps;
|
Fix a long standing race between sleep queue and thread
suspension code. When a thread A is going to sleep, it calls
sleepq_catch_signals() to detect any pending signals or thread
suspension request, if nothing happens, it returns without
holding process lock or scheduler lock, this opens a race
window which allows thread B to come in and do process
suspension work, however since A is still at running state,
thread B can do nothing to A, thread A continues, and puts
itself into actually sleeping state, but B has never seen it,
and it sits there forever until B is woken up by other threads
sometimes later(this can be very long delay or never
happen). Fix this bug by forcing sleepq_catch_signals to
return with scheduler lock held.
Fix sleepq_abort() by passing it an interrupted code, previously,
it worked as wakeup_one(), and the interruption can not be
identified correctly by sleep queue code when the sleeping
thread is resumed.
Let thread_suspend_check() returns EINTR or ERESTART, so sleep
queue no longer has to use SIGSTOP as a hack to build a return
value.
Reviewed by: jhb
MFC after: 1 week
2006-02-15 23:52:01 +00:00
|
|
|
int intrval;
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
int ret = 0;
|
If a thread that is swapped out is made runnable, then the setrunnable()
routine wakes up proc0 so that proc0 can swap the thread back in.
Historically, this has been done by waking up proc0 directly from
setrunnable() itself via a wakeup(). When waking up a sleeping thread
that was swapped out (the usual case when waking proc0 since only sleeping
threads are eligible to be swapped out), this resulted in a bit of
recursion (e.g. wakeup() -> setrunnable() -> wakeup()).
With sleep queues having separate locks in 6.x and later, this caused a
spin lock LOR (sleepq lock -> sched_lock/thread lock -> sleepq lock).
An attempt was made to fix this in 7.0 by making the proc0 wakeup use
the ithread mechanism for doing the wakeup. However, this required
grabbing proc0's thread lock to perform the wakeup. If proc0 was asleep
elsewhere in the kernel (e.g. waiting for disk I/O), then this degenerated
into the same LOR since the thread lock would be some other sleepq lock.
Fix this by deferring the wakeup of the swapper until after the sleepq
lock held by the upper layer has been locked. The setrunnable() routine
now returns a boolean value to indicate whether or not proc0 needs to be
woken up. The end result is that consumers of the sleepq API such as
*sleep/wakeup, condition variables, sx locks, and lockmgr, have to wakeup
proc0 if they get a non-zero return value from sleepq_abort(),
sleepq_broadcast(), or sleepq_signal().
Discussed with: jeff
Glanced at by: sam
Tested by: Jurgen Weber jurgen - ish com au
MFC after: 2 weeks
2008-08-05 20:02:31 +00:00
|
|
|
int wakeup_swapper;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2010-10-09 02:50:23 +00:00
|
|
|
MPASS(td == NULL || p == td->td_proc);
|
2005-11-03 04:49:16 +00:00
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
|
|
|
|
2003-08-10 23:05:37 +00:00
|
|
|
if (!_SIG_VALID(sig))
|
2010-07-20 02:23:12 +00:00
|
|
|
panic("%s(): invalid signal %d", __func__, sig);
|
2003-03-31 22:49:17 +00:00
|
|
|
|
2010-07-20 02:23:12 +00:00
|
|
|
KASSERT(ksi == NULL || !KSI_ONQ(ksi), ("%s: ksi on queue", __func__));
|
1999-09-29 15:03:48 +00:00
|
|
|
|
2005-11-03 04:49:16 +00:00
|
|
|
/*
|
|
|
|
* IEEE Std 1003.1-2001: return success when killing a zombie.
|
|
|
|
*/
|
|
|
|
if (p->p_state == PRS_ZOMBIE) {
|
|
|
|
if (ksi && (ksi->ksi_flags & KSI_INS))
|
|
|
|
ksiginfo_tryfree(ksi);
|
|
|
|
return (ret);
|
|
|
|
}
|
2000-04-16 18:53:38 +00:00
|
|
|
|
2005-11-03 04:49:16 +00:00
|
|
|
ps = p->p_sigacts;
|
When filt_proc() removes event from the knlist due to the process
exiting (NOTE_EXIT->knlist_remove_inevent()), two things happen:
- knote kn_knlist pointer is reset
- INFLUX knote is removed from the process knlist.
And, there are two consequences:
- KN_LIST_UNLOCK() on such knote is nop
- there is nothing which would block exit1() from processing past the
knlist_destroy() (and knlist_destroy() resets knlist lock pointers).
Both consequences result either in leaked process lock, or
dereferencing NULL function pointers for locking.
Handle this by stopping embedding the process knlist into struct proc.
Instead, the knlist is allocated together with struct proc, but marked
as autodestroy on the zombie reap, by knlist_detach() function. The
knlist is freed when last kevent is removed from the list, in
particular, at the zombie reap time if the list is empty. As result,
the knlist_remove_inevent() is no longer needed and removed.
Other changes:
In filt_procattach(), clear NOTE_EXEC and NOTE_FORK desired events
from kn_sfflags for knote registered by kernel to only get NOTE_CHILD
notifications. The flags leak resulted in excessive
NOTE_EXEC/NOTE_FORK reports.
Fix immediate note activation in filt_procattach(). Condition should
be either the immediate CHILD_NOTE activation, or immediate NOTE_EXIT
report for the exiting process.
In knote_fork(), do not perform racy check for KN_INFLUX before kq
lock is taken. Besides being racy, it did not accounted for notes
just added by scan (KN_SCAN).
Some minor and incomplete style fixes.
Analyzed and tested by: Eric Badger <eric@badgerio.us>
Reviewed by: jhb
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Approved by: re (gjb)
Differential revision: https://reviews.freebsd.org/D6859
2016-06-27 21:52:17 +00:00
|
|
|
KNOTE_LOCKED(p->p_klist, NOTE_SIGNAL | sig);
|
1999-09-29 15:03:48 +00:00
|
|
|
prop = sigprop(sig);
|
2003-03-31 22:49:17 +00:00
|
|
|
|
2005-11-03 04:49:16 +00:00
|
|
|
if (td == NULL) {
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
td = sigtd(p, sig, false);
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
sigqueue = &p->p_sigqueue;
|
2013-07-22 00:44:37 +00:00
|
|
|
} else
|
2005-11-03 04:49:16 +00:00
|
|
|
sigqueue = &td->td_sigqueue;
|
2003-03-31 22:49:17 +00:00
|
|
|
|
2015-12-16 23:39:27 +00:00
|
|
|
SDT_PROBE3(proc, , , signal__send, td, p, sig);
|
2008-05-24 06:22:16 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2005-06-06 05:13:10 +00:00
|
|
|
* If the signal is being ignored,
|
|
|
|
* then we forget about it immediately.
|
|
|
|
* (Note: we don't set SIGCONT in ps_sigignore,
|
|
|
|
* and if it is set to SIG_IGN,
|
|
|
|
* action will be SIG_DFL here.)
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2005-06-06 05:13:10 +00:00
|
|
|
mtx_lock(&ps->ps_mtx);
|
2006-10-20 16:19:21 +00:00
|
|
|
if (SIGISMEMBER(ps->ps_sigignore, sig)) {
|
2015-12-16 23:39:27 +00:00
|
|
|
SDT_PROBE3(proc, , , signal__discard, td, p, sig);
|
2008-05-24 06:22:16 +00:00
|
|
|
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_unlock(&ps->ps_mtx);
|
2005-11-03 04:49:16 +00:00
|
|
|
if (ksi && (ksi->ksi_flags & KSI_INS))
|
|
|
|
ksiginfo_tryfree(ksi);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
return (ret);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2005-06-06 05:13:10 +00:00
|
|
|
if (SIGISMEMBER(td->td_sigmask, sig))
|
|
|
|
action = SIG_HOLD;
|
|
|
|
else if (SIGISMEMBER(ps->ps_sigcatch, sig))
|
|
|
|
action = SIG_CATCH;
|
|
|
|
else
|
|
|
|
action = SIG_DFL;
|
Fix a long standing race between sleep queue and thread
suspension code. When a thread A is going to sleep, it calls
sleepq_catch_signals() to detect any pending signals or thread
suspension request, if nothing happens, it returns without
holding process lock or scheduler lock, this opens a race
window which allows thread B to come in and do process
suspension work, however since A is still at running state,
thread B can do nothing to A, thread A continues, and puts
itself into actually sleeping state, but B has never seen it,
and it sits there forever until B is woken up by other threads
sometimes later(this can be very long delay or never
happen). Fix this bug by forcing sleepq_catch_signals to
return with scheduler lock held.
Fix sleepq_abort() by passing it an interrupted code, previously,
it worked as wakeup_one(), and the interruption can not be
identified correctly by sleep queue code when the sleeping
thread is resumed.
Let thread_suspend_check() returns EINTR or ERESTART, so sleep
queue no longer has to use SIGSTOP as a hack to build a return
value.
Reviewed by: jhb
MFC after: 1 week
2006-02-15 23:52:01 +00:00
|
|
|
if (SIGISMEMBER(ps->ps_sigintr, sig))
|
|
|
|
intrval = EINTR;
|
|
|
|
else
|
|
|
|
intrval = ERESTART;
|
2005-06-06 05:13:10 +00:00
|
|
|
mtx_unlock(&ps->ps_mtx);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2016-09-02 18:22:56 +00:00
|
|
|
if (prop & SIGPROP_CONT)
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sigqueue_delete_stopmask_proc(p);
|
2016-09-02 18:22:56 +00:00
|
|
|
else if (prop & SIGPROP_STOP) {
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* If sending a tty stop signal to a member of an orphaned
|
|
|
|
* process group, discard the signal here if the action
|
|
|
|
* is default; don't stop the process below if sleeping,
|
|
|
|
* and don't clear any pending SIGCONT.
|
|
|
|
*/
|
2016-09-02 18:22:56 +00:00
|
|
|
if ((prop & SIGPROP_TTYSTOP) &&
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
(p->p_pgrp->pg_jobc == 0) &&
|
2005-11-03 04:49:16 +00:00
|
|
|
(action == SIG_DFL)) {
|
|
|
|
if (ksi && (ksi->ksi_flags & KSI_INS))
|
|
|
|
ksiginfo_tryfree(ksi);
|
|
|
|
return (ret);
|
|
|
|
}
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sigqueue_delete_proc(p, SIGCONT);
|
2005-11-08 09:09:26 +00:00
|
|
|
if (p->p_flag & P_CONTINUED) {
|
|
|
|
p->p_flag &= ~P_CONTINUED;
|
|
|
|
PROC_LOCK(p->p_pptr);
|
|
|
|
sigqueue_take(p->p_ksi);
|
|
|
|
PROC_UNLOCK(p->p_pptr);
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2003-07-17 22:52:55 +00:00
|
|
|
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
ret = sigqueue_add(sigqueue, sig, ksi);
|
|
|
|
if (ret != 0)
|
|
|
|
return (ret);
|
2005-11-03 04:49:16 +00:00
|
|
|
signotify(td);
|
2003-04-12 00:38:47 +00:00
|
|
|
/*
|
|
|
|
* Defer further processing for signals which are held,
|
|
|
|
* except that stopped processes must be continued by SIGCONT.
|
|
|
|
*/
|
|
|
|
if (action == SIG_HOLD &&
|
2016-09-02 18:22:56 +00:00
|
|
|
!((prop & SIGPROP_CONT) && (p->p_flag & P_STOPPED_SIG)))
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
return (ret);
|
2017-03-16 13:03:31 +00:00
|
|
|
|
2019-12-15 21:11:15 +00:00
|
|
|
wakeup_swapper = 0;
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
* Some signals have a process-wide effect and a per-thread
|
|
|
|
* component. Most processing occurs when the process next
|
|
|
|
* tries to cross the user boundary, however there are some
|
2013-03-18 18:04:09 +00:00
|
|
|
* times when processing needs to be done immediately, such as
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
* waking up threads so that they can cross the user boundary.
|
2013-03-18 18:04:09 +00:00
|
|
|
* We try to do the per-process part here.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
if (P_SHOULDSTOP(p)) {
|
2012-09-13 15:51:18 +00:00
|
|
|
KASSERT(!(p->p_flag & P_WEXIT),
|
|
|
|
("signal to stopped but exiting process"));
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
if (sig == SIGKILL) {
|
2010-09-01 01:26:07 +00:00
|
|
|
/*
|
|
|
|
* If traced process is already stopped,
|
|
|
|
* then no further action is necessary.
|
|
|
|
*/
|
2010-08-31 07:15:50 +00:00
|
|
|
if (p->p_flag & P_TRACED)
|
|
|
|
goto out;
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
/*
|
|
|
|
* SIGKILL sets process running.
|
|
|
|
* It will die elsewhere.
|
|
|
|
* All threads must be restarted.
|
|
|
|
*/
|
2004-10-03 13:23:49 +00:00
|
|
|
p->p_flag &= ~P_STOPPED_SIG;
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
goto runfast;
|
|
|
|
}
|
|
|
|
|
2016-09-02 18:22:56 +00:00
|
|
|
if (prop & SIGPROP_CONT) {
|
2010-09-01 01:26:07 +00:00
|
|
|
/*
|
|
|
|
* If traced process is already stopped,
|
|
|
|
* then no further action is necessary.
|
|
|
|
*/
|
2010-08-31 07:15:50 +00:00
|
|
|
if (p->p_flag & P_TRACED)
|
|
|
|
goto out;
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
/*
|
|
|
|
* If SIGCONT is default (or ignored), we continue the
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
* process but don't leave the signal in sigqueue as
|
2002-10-01 17:15:53 +00:00
|
|
|
* it has no further action. If SIGCONT is held, we
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
* continue the process and leave the signal in
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
* sigqueue. If the process catches SIGCONT, let it
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
* handle the signal itself. If it isn't waiting on
|
|
|
|
* an event, it goes back to run state.
|
|
|
|
* Otherwise, process goes back to sleep state.
|
|
|
|
*/
|
2002-09-05 07:30:18 +00:00
|
|
|
p->p_flag &= ~P_STOPPED_SIG;
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SLOCK(p);
|
2005-11-08 09:09:26 +00:00
|
|
|
if (p->p_numthreads == p->p_suspcount) {
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SUNLOCK(p);
|
2005-11-08 09:09:26 +00:00
|
|
|
p->p_flag |= P_CONTINUED;
|
2015-07-18 09:02:50 +00:00
|
|
|
p->p_xsig = SIGCONT;
|
2006-02-04 14:10:57 +00:00
|
|
|
PROC_LOCK(p->p_pptr);
|
2005-11-08 09:09:26 +00:00
|
|
|
childproc_continued(p);
|
2006-02-04 14:10:57 +00:00
|
|
|
PROC_UNLOCK(p->p_pptr);
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SLOCK(p);
|
2005-11-08 09:09:26 +00:00
|
|
|
}
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
if (action == SIG_DFL) {
|
Commit 4/14 of sched_lock decomposition.
- Use thread_lock() rather than sched_lock for per-thread scheduling
sychronization.
- Use the per-process spinlock rather than the sched_lock for per-process
scheduling synchronization.
- Move some common code into thread_suspend_switch() to handle the
mechanics of suspending a thread. The locking here is incredibly
convoluted and should be simplified.
Tested by: kris, current@
Tested on: i386, amd64, ULE, 4BSD, libthr, libkse, PREEMPTION, etc.
Discussed with: kris, attilio, kmacy, jhb, julian, bde (small parts each)
2007-06-04 23:52:24 +00:00
|
|
|
thread_unsuspend(p);
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SUNLOCK(p);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sigqueue_delete(sigqueue, sig);
|
Commit 4/14 of sched_lock decomposition.
- Use thread_lock() rather than sched_lock for per-thread scheduling
sychronization.
- Use the per-process spinlock rather than the sched_lock for per-process
scheduling synchronization.
- Move some common code into thread_suspend_switch() to handle the
mechanics of suspending a thread. The locking here is incredibly
convoluted and should be simplified.
Tested by: kris, current@
Tested on: i386, amd64, ULE, 4BSD, libthr, libkse, PREEMPTION, etc.
Discussed with: kris, attilio, kmacy, jhb, julian, bde (small parts each)
2007-06-04 23:52:24 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (action == SIG_CATCH) {
|
2006-10-26 21:42:22 +00:00
|
|
|
/*
|
|
|
|
* The process wants to catch it so it needs
|
|
|
|
* to run at least one thread, but which one?
|
|
|
|
*/
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SUNLOCK(p);
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
goto runfast;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* The signal is not ignored or caught.
|
|
|
|
*/
|
2002-08-01 18:45:10 +00:00
|
|
|
thread_unsuspend(p);
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SUNLOCK(p);
|
1994-05-24 10:09:53 +00:00
|
|
|
goto out;
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
}
|
|
|
|
|
2016-09-02 18:22:56 +00:00
|
|
|
if (prop & SIGPROP_STOP) {
|
2010-09-01 01:26:07 +00:00
|
|
|
/*
|
|
|
|
* If traced process is already stopped,
|
|
|
|
* then no further action is necessary.
|
|
|
|
*/
|
2010-08-31 07:15:50 +00:00
|
|
|
if (p->p_flag & P_TRACED)
|
|
|
|
goto out;
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
/*
|
|
|
|
* Already stopped, don't need to stop again
|
|
|
|
* (If we did the shell could get confused).
|
2002-08-01 18:45:10 +00:00
|
|
|
* Just make sure the signal STOP bit set.
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
*/
|
2002-09-05 07:30:18 +00:00
|
|
|
p->p_flag |= P_STOPPED_SIG;
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sigqueue_delete(sigqueue, sig);
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
* All other kinds of signals:
|
|
|
|
* If a thread is sleeping interruptibly, simulate a
|
|
|
|
* wakeup so that when it is continued it will be made
|
|
|
|
* runnable and can look at the signal. However, don't make
|
2002-08-01 18:45:10 +00:00
|
|
|
* the PROCESS runnable, leave it stopped.
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
* It may run a bit until it hits a thread_suspend_check().
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SLOCK(p);
|
Commit 4/14 of sched_lock decomposition.
- Use thread_lock() rather than sched_lock for per-thread scheduling
sychronization.
- Use the per-process spinlock rather than the sched_lock for per-process
scheduling synchronization.
- Move some common code into thread_suspend_switch() to handle the
mechanics of suspending a thread. The locking here is incredibly
convoluted and should be simplified.
Tested by: kris, current@
Tested on: i386, amd64, ULE, 4BSD, libthr, libkse, PREEMPTION, etc.
Discussed with: kris, attilio, kmacy, jhb, julian, bde (small parts each)
2007-06-04 23:52:24 +00:00
|
|
|
thread_lock(td);
|
2019-12-15 21:11:15 +00:00
|
|
|
if (TD_CAN_ABORT(td))
|
If a thread that is swapped out is made runnable, then the setrunnable()
routine wakes up proc0 so that proc0 can swap the thread back in.
Historically, this has been done by waking up proc0 directly from
setrunnable() itself via a wakeup(). When waking up a sleeping thread
that was swapped out (the usual case when waking proc0 since only sleeping
threads are eligible to be swapped out), this resulted in a bit of
recursion (e.g. wakeup() -> setrunnable() -> wakeup()).
With sleep queues having separate locks in 6.x and later, this caused a
spin lock LOR (sleepq lock -> sched_lock/thread lock -> sleepq lock).
An attempt was made to fix this in 7.0 by making the proc0 wakeup use
the ithread mechanism for doing the wakeup. However, this required
grabbing proc0's thread lock to perform the wakeup. If proc0 was asleep
elsewhere in the kernel (e.g. waiting for disk I/O), then this degenerated
into the same LOR since the thread lock would be some other sleepq lock.
Fix this by deferring the wakeup of the swapper until after the sleepq
lock held by the upper layer has been locked. The setrunnable() routine
now returns a boolean value to indicate whether or not proc0 needs to be
woken up. The end result is that consumers of the sleepq API such as
*sleep/wakeup, condition variables, sx locks, and lockmgr, have to wakeup
proc0 if they get a non-zero return value from sleepq_abort(),
sleepq_broadcast(), or sleepq_signal().
Discussed with: jeff
Glanced at by: sam
Tested by: Jurgen Weber jurgen - ish com au
MFC after: 2 weeks
2008-08-05 20:02:31 +00:00
|
|
|
wakeup_swapper = sleepq_abort(td, intrval);
|
2019-12-15 21:11:15 +00:00
|
|
|
else
|
|
|
|
thread_unlock(td);
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SUNLOCK(p);
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
goto out;
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2004-03-29 22:46:54 +00:00
|
|
|
* Mutexes are short lived. Threads waiting on them will
|
|
|
|
* hit thread_suspend_check() soon.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2005-06-06 05:13:10 +00:00
|
|
|
} else if (p->p_state == PRS_NORMAL) {
|
|
|
|
if (p->p_flag & P_TRACED || action == SIG_CATCH) {
|
Fix a long standing race between sleep queue and thread
suspension code. When a thread A is going to sleep, it calls
sleepq_catch_signals() to detect any pending signals or thread
suspension request, if nothing happens, it returns without
holding process lock or scheduler lock, this opens a race
window which allows thread B to come in and do process
suspension work, however since A is still at running state,
thread B can do nothing to A, thread A continues, and puts
itself into actually sleeping state, but B has never seen it,
and it sits there forever until B is woken up by other threads
sometimes later(this can be very long delay or never
happen). Fix this bug by forcing sleepq_catch_signals to
return with scheduler lock held.
Fix sleepq_abort() by passing it an interrupted code, previously,
it worked as wakeup_one(), and the interruption can not be
identified correctly by sleep queue code when the sleeping
thread is resumed.
Let thread_suspend_check() returns EINTR or ERESTART, so sleep
queue no longer has to use SIGSTOP as a hack to build a return
value.
Reviewed by: jhb
MFC after: 1 week
2006-02-15 23:52:01 +00:00
|
|
|
tdsigwakeup(td, sig, action, intrval);
|
1994-05-24 10:09:53 +00:00
|
|
|
goto out;
|
2002-08-21 20:03:55 +00:00
|
|
|
}
|
2005-06-06 05:13:10 +00:00
|
|
|
|
|
|
|
MPASS(action == SIG_DFL);
|
|
|
|
|
2016-09-02 18:22:56 +00:00
|
|
|
if (prop & SIGPROP_STOP) {
|
2012-09-13 15:51:18 +00:00
|
|
|
if (p->p_flag & (P_PPWAIT|P_WEXIT))
|
In the kernel code, we have the tsleep() call with the PCATCH argument.
PCATCH means 'if we get a signal, interrupt me!" and tsleep returns
either EINTR or ERESTART depending on the circumstances. ERESTART is
"special" because it causes the system call to fail, but right as it
returns back to userland it tells the trap handler to move %eip back a
bit so that userland will immediately re-run the syscall.
This is a syscall restart. It only works for things like read() etc where
nothing has changed yet. Note that *userland* is tricked into restarting
the syscall by the kernel. The kernel doesn't actually do the restart. It
is deadly for things like select, poll, nanosleep etc where it might cause
the elapsed time to be reset and start again from scratch. So those
syscalls do this to prevent userland rerunning the syscall:
if (error == ERESTART) error = EINTR;
Fake "signals" like SIGTSTP from ^Z etc do not normally invoke userland
signal handlers. But, in -current, the PCATCH *is* being triggered and
tsleep is returning ERESTART, and the syscall is aborted even though no
userland signal handler was run.
That is the fault here. We're triggering the PCATCH in cases that we
shouldn't. ie: it is being triggered on *any* signal processing, rather
than the case where the signal is posted to userland.
--- Peter
The work of psignal() is a patchwork of special case required by the process
debugging and job-control facilities...
--- Kirk McKusick
"The design and impelementation of the 4.4BSD Operating system"
Page 105
in STABLE source, when psignal is posting a STOP signal to sleeping
process and the signal action of the process is SIG_DFL, system will
directly change the process state from SSLEEP to SSTOP, and when
SIGCONT is posted to the stopped process, if it finds that the process
is still on sleep queue, the process state will be restored to SSLEEP,
and won't wakeup the process.
this commit mimics the behaviour in STABLE source tree.
Reviewed by: Jon Mini, Tim Robbins, Peter Wemm
Approved by: julian@freebsd.org (mentor)
2002-09-03 12:56:01 +00:00
|
|
|
goto out;
|
2003-03-11 00:07:53 +00:00
|
|
|
p->p_flag |= P_STOPPED_SIG;
|
2015-07-18 09:02:50 +00:00
|
|
|
p->p_xsig = sig;
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SLOCK(p);
|
2016-06-28 16:41:50 +00:00
|
|
|
wakeup_swapper = sig_suspend_threads(td, p, 1);
|
2003-03-31 22:49:17 +00:00
|
|
|
if (p->p_numthreads == p->p_suspcount) {
|
2005-11-08 09:09:26 +00:00
|
|
|
/*
|
|
|
|
* only thread sending signal to another
|
|
|
|
* process can reach here, if thread is sending
|
|
|
|
* signal to its process, because thread does
|
|
|
|
* not suspend itself here, p_numthreads
|
|
|
|
* should never be equal to p_suspcount.
|
|
|
|
*/
|
|
|
|
thread_stopped(p);
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SUNLOCK(p);
|
2015-07-18 09:02:50 +00:00
|
|
|
sigqueue_delete_proc(p, p->p_xsig);
|
2008-11-05 03:01:23 +00:00
|
|
|
} else
|
|
|
|
PROC_SUNLOCK(p);
|
In the kernel code, we have the tsleep() call with the PCATCH argument.
PCATCH means 'if we get a signal, interrupt me!" and tsleep returns
either EINTR or ERESTART depending on the circumstances. ERESTART is
"special" because it causes the system call to fail, but right as it
returns back to userland it tells the trap handler to move %eip back a
bit so that userland will immediately re-run the syscall.
This is a syscall restart. It only works for things like read() etc where
nothing has changed yet. Note that *userland* is tricked into restarting
the syscall by the kernel. The kernel doesn't actually do the restart. It
is deadly for things like select, poll, nanosleep etc where it might cause
the elapsed time to be reset and start again from scratch. So those
syscalls do this to prevent userland rerunning the syscall:
if (error == ERESTART) error = EINTR;
Fake "signals" like SIGTSTP from ^Z etc do not normally invoke userland
signal handlers. But, in -current, the PCATCH *is* being triggered and
tsleep is returning ERESTART, and the syscall is aborted even though no
userland signal handler was run.
That is the fault here. We're triggering the PCATCH in cases that we
shouldn't. ie: it is being triggered on *any* signal processing, rather
than the case where the signal is posted to userland.
--- Peter
The work of psignal() is a patchwork of special case required by the process
debugging and job-control facilities...
--- Kirk McKusick
"The design and impelementation of the 4.4BSD Operating system"
Page 105
in STABLE source, when psignal is posting a STOP signal to sleeping
process and the signal action of the process is SIG_DFL, system will
directly change the process state from SSLEEP to SSTOP, and when
SIGCONT is posted to the stopped process, if it finds that the process
is still on sleep queue, the process state will be restored to SSLEEP,
and won't wakeup the process.
this commit mimics the behaviour in STABLE source tree.
Reviewed by: Jon Mini, Tim Robbins, Peter Wemm
Approved by: julian@freebsd.org (mentor)
2002-09-03 12:56:01 +00:00
|
|
|
goto out;
|
2008-03-19 06:19:01 +00:00
|
|
|
}
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
} else {
|
|
|
|
/* Not in "NORMAL" state. discard the signal. */
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sigqueue_delete(sigqueue, sig);
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
goto out;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
/*
|
|
|
|
* The process is not stopped so we need to apply the signal to all the
|
|
|
|
* running threads.
|
|
|
|
*/
|
|
|
|
runfast:
|
Fix a long standing race between sleep queue and thread
suspension code. When a thread A is going to sleep, it calls
sleepq_catch_signals() to detect any pending signals or thread
suspension request, if nothing happens, it returns without
holding process lock or scheduler lock, this opens a race
window which allows thread B to come in and do process
suspension work, however since A is still at running state,
thread B can do nothing to A, thread A continues, and puts
itself into actually sleeping state, but B has never seen it,
and it sits there forever until B is woken up by other threads
sometimes later(this can be very long delay or never
happen). Fix this bug by forcing sleepq_catch_signals to
return with scheduler lock held.
Fix sleepq_abort() by passing it an interrupted code, previously,
it worked as wakeup_one(), and the interruption can not be
identified correctly by sleep queue code when the sleeping
thread is resumed.
Let thread_suspend_check() returns EINTR or ERESTART, so sleep
queue no longer has to use SIGSTOP as a hack to build a return
value.
Reviewed by: jhb
MFC after: 1 week
2006-02-15 23:52:01 +00:00
|
|
|
tdsigwakeup(td, sig, action, intrval);
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SLOCK(p);
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
thread_unsuspend(p);
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SUNLOCK(p);
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
out:
|
2008-11-05 03:01:23 +00:00
|
|
|
/* If we jump here, proc slock should not be owned. */
|
|
|
|
PROC_SLOCK_ASSERT(p, MA_NOTOWNED);
|
2019-12-15 21:11:15 +00:00
|
|
|
if (wakeup_swapper)
|
|
|
|
kick_proc0();
|
|
|
|
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
return (ret);
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
/*
|
|
|
|
* The force of a signal has been directed against a single
|
2004-05-21 10:02:24 +00:00
|
|
|
* thread. We need to see what we can do about knocking it
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
* out of any sleep it may be in etc.
|
|
|
|
*/
|
|
|
|
static void
|
Fix a long standing race between sleep queue and thread
suspension code. When a thread A is going to sleep, it calls
sleepq_catch_signals() to detect any pending signals or thread
suspension request, if nothing happens, it returns without
holding process lock or scheduler lock, this opens a race
window which allows thread B to come in and do process
suspension work, however since A is still at running state,
thread B can do nothing to A, thread A continues, and puts
itself into actually sleeping state, but B has never seen it,
and it sits there forever until B is woken up by other threads
sometimes later(this can be very long delay or never
happen). Fix this bug by forcing sleepq_catch_signals to
return with scheduler lock held.
Fix sleepq_abort() by passing it an interrupted code, previously,
it worked as wakeup_one(), and the interruption can not be
identified correctly by sleep queue code when the sleeping
thread is resumed.
Let thread_suspend_check() returns EINTR or ERESTART, so sleep
queue no longer has to use SIGSTOP as a hack to build a return
value.
Reviewed by: jhb
MFC after: 1 week
2006-02-15 23:52:01 +00:00
|
|
|
tdsigwakeup(struct thread *td, int sig, sig_t action, int intrval)
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
{
|
|
|
|
struct proc *p = td->td_proc;
|
2019-12-15 21:11:15 +00:00
|
|
|
int prop, wakeup_swapper;
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
|
2003-04-18 20:59:05 +00:00
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
prop = sigprop(sig);
|
2004-05-21 10:02:24 +00:00
|
|
|
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SLOCK(p);
|
2008-03-19 06:19:01 +00:00
|
|
|
thread_lock(td);
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
/*
|
2002-07-03 09:15:20 +00:00
|
|
|
* Bring the priority of a thread up if we want it to get
|
2015-05-29 16:26:08 +00:00
|
|
|
* killed in this lifetime. Be careful to avoid bumping the
|
|
|
|
* priority of the idle thread, since we still allow to signal
|
|
|
|
* kernel processes.
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
*/
|
2016-09-02 18:22:56 +00:00
|
|
|
if (action == SIG_DFL && (prop & SIGPROP_KILL) != 0 &&
|
2015-05-29 16:26:08 +00:00
|
|
|
td->td_priority > PUSER && !TD_IS_IDLETHREAD(td))
|
2007-07-19 08:49:16 +00:00
|
|
|
sched_prio(td, PUSER);
|
2004-05-20 20:17:28 +00:00
|
|
|
if (TD_ON_SLEEPQ(td)) {
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
/*
|
|
|
|
* If thread is sleeping uninterruptibly
|
|
|
|
* we can't interrupt the sleep... the signal will
|
|
|
|
* be noticed when the process returns through
|
|
|
|
* trap() or syscall().
|
|
|
|
*/
|
Switch the sleep/wakeup and condition variable implementations to use the
sleep queue interface:
- Sleep queues attempt to merge some of the benefits of both sleep queues
and condition variables. Having sleep qeueus in a hash table avoids
having to allocate a queue head for each wait channel. Thus, struct cv
has shrunk down to just a single char * pointer now. However, the
hash table does not hold threads directly, but queue heads. This means
that once you have located a queue in the hash bucket, you no longer have
to walk the rest of the hash chain looking for threads. Instead, you have
a list of all the threads sleeping on that wait channel.
- Outside of the sleepq code and the sleep/cv code the kernel no longer
differentiates between cv's and sleep/wakeup. For example, calls to
abortsleep() and cv_abort() are replaced with a call to sleepq_abort().
Thus, the TDF_CVWAITQ flag is removed. Also, calls to unsleep() and
cv_waitq_remove() have been replaced with calls to sleepq_remove().
- The sched_sleep() function no longer accepts a priority argument as
sleep's no longer inherently bump the priority. Instead, this is soley
a propery of msleep() which explicitly calls sched_prio() before
blocking.
- The TDF_ONSLEEPQ flag has been dropped as it was never used. The
associated TDF_SET_ONSLEEPQ and TDF_CLR_ON_SLEEPQ macros have also been
dropped and replaced with a single explicit clearing of td_wchan.
TD_SET_ONSLEEPQ() would really have only made sense if it had taken
the wait channel and message as arguments anyway. Now that that only
happens in one place, a macro would be overkill.
2004-02-27 18:52:44 +00:00
|
|
|
if ((td->td_flags & TDF_SINTR) == 0)
|
2008-03-19 06:19:01 +00:00
|
|
|
goto out;
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2005-06-06 05:13:10 +00:00
|
|
|
* If SIGCONT is default (or ignored) and process is
|
|
|
|
* asleep, we are finished; the process should not
|
|
|
|
* be awakened.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2016-09-02 18:22:56 +00:00
|
|
|
if ((prop & SIGPROP_CONT) && action == SIG_DFL) {
|
Commit 4/14 of sched_lock decomposition.
- Use thread_lock() rather than sched_lock for per-thread scheduling
sychronization.
- Use the per-process spinlock rather than the sched_lock for per-process
scheduling synchronization.
- Move some common code into thread_suspend_switch() to handle the
mechanics of suspending a thread. The locking here is incredibly
convoluted and should be simplified.
Tested by: kris, current@
Tested on: i386, amd64, ULE, 4BSD, libthr, libkse, PREEMPTION, etc.
Discussed with: kris, attilio, kmacy, jhb, julian, bde (small parts each)
2007-06-04 23:52:24 +00:00
|
|
|
thread_unlock(td);
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SUNLOCK(p);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sigqueue_delete(&p->p_sigqueue, sig);
|
2002-07-03 09:15:20 +00:00
|
|
|
/*
|
2005-06-06 05:13:10 +00:00
|
|
|
* It may be on either list in this state.
|
|
|
|
* Remove from both for now.
|
2002-07-03 09:15:20 +00:00
|
|
|
*/
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sigqueue_delete(&td->td_sigqueue, sig);
|
2005-06-06 05:13:10 +00:00
|
|
|
return;
|
2002-07-03 09:15:20 +00:00
|
|
|
}
|
2005-06-06 05:13:10 +00:00
|
|
|
|
2013-02-06 17:06:51 +00:00
|
|
|
/*
|
|
|
|
* Don't awaken a sleeping thread for SIGSTOP if the
|
|
|
|
* STOP signal is deferred.
|
|
|
|
*/
|
2016-09-02 18:22:56 +00:00
|
|
|
if ((prop & SIGPROP_STOP) != 0 && (td->td_flags & (TDF_SBDRY |
|
2016-06-28 16:41:50 +00:00
|
|
|
TDF_SERESTART | TDF_SEINTR)) == TDF_SBDRY)
|
2013-02-06 17:06:51 +00:00
|
|
|
goto out;
|
|
|
|
|
2005-06-06 05:13:10 +00:00
|
|
|
/*
|
|
|
|
* Give low priority threads a better chance to run.
|
|
|
|
*/
|
2015-05-29 16:26:08 +00:00
|
|
|
if (td->td_priority > PUSER && !TD_IS_IDLETHREAD(td))
|
2005-06-06 05:13:10 +00:00
|
|
|
sched_prio(td, PUSER);
|
|
|
|
|
If a thread that is swapped out is made runnable, then the setrunnable()
routine wakes up proc0 so that proc0 can swap the thread back in.
Historically, this has been done by waking up proc0 directly from
setrunnable() itself via a wakeup(). When waking up a sleeping thread
that was swapped out (the usual case when waking proc0 since only sleeping
threads are eligible to be swapped out), this resulted in a bit of
recursion (e.g. wakeup() -> setrunnable() -> wakeup()).
With sleep queues having separate locks in 6.x and later, this caused a
spin lock LOR (sleepq lock -> sched_lock/thread lock -> sleepq lock).
An attempt was made to fix this in 7.0 by making the proc0 wakeup use
the ithread mechanism for doing the wakeup. However, this required
grabbing proc0's thread lock to perform the wakeup. If proc0 was asleep
elsewhere in the kernel (e.g. waiting for disk I/O), then this degenerated
into the same LOR since the thread lock would be some other sleepq lock.
Fix this by deferring the wakeup of the swapper until after the sleepq
lock held by the upper layer has been locked. The setrunnable() routine
now returns a boolean value to indicate whether or not proc0 needs to be
woken up. The end result is that consumers of the sleepq API such as
*sleep/wakeup, condition variables, sx locks, and lockmgr, have to wakeup
proc0 if they get a non-zero return value from sleepq_abort(),
sleepq_broadcast(), or sleepq_signal().
Discussed with: jeff
Glanced at by: sam
Tested by: Jurgen Weber jurgen - ish com au
MFC after: 2 weeks
2008-08-05 20:02:31 +00:00
|
|
|
wakeup_swapper = sleepq_abort(td, intrval);
|
2019-12-15 21:11:15 +00:00
|
|
|
PROC_SUNLOCK(p);
|
|
|
|
if (wakeup_swapper)
|
|
|
|
kick_proc0();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Other states do nothing with the signal immediately,
|
|
|
|
* other than kicking ourselves if we are running.
|
|
|
|
* It will either never be noticed, or noticed very soon.
|
|
|
|
*/
|
2004-05-21 10:02:24 +00:00
|
|
|
#ifdef SMP
|
2019-12-15 21:11:15 +00:00
|
|
|
if (TD_IS_RUNNING(td) && td != curthread)
|
|
|
|
forward_signal(td);
|
2002-07-03 09:15:20 +00:00
|
|
|
#endif
|
2019-12-15 21:11:15 +00:00
|
|
|
|
2008-03-19 06:19:01 +00:00
|
|
|
out:
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SUNLOCK(p);
|
2008-03-19 06:19:01 +00:00
|
|
|
thread_unlock(td);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2016-06-28 16:41:50 +00:00
|
|
|
static int
|
2006-02-13 03:16:55 +00:00
|
|
|
sig_suspend_threads(struct thread *td, struct proc *p, int sending)
|
|
|
|
{
|
|
|
|
struct thread *td2;
|
2016-06-28 16:41:50 +00:00
|
|
|
int wakeup_swapper;
|
2006-02-13 03:16:55 +00:00
|
|
|
|
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SLOCK_ASSERT(p, MA_OWNED);
|
2017-05-11 17:03:45 +00:00
|
|
|
MPASS(sending || td == curthread);
|
2006-02-13 03:16:55 +00:00
|
|
|
|
2016-06-28 16:41:50 +00:00
|
|
|
wakeup_swapper = 0;
|
2006-02-13 03:16:55 +00:00
|
|
|
FOREACH_THREAD_IN_PROC(p, td2) {
|
Commit 4/14 of sched_lock decomposition.
- Use thread_lock() rather than sched_lock for per-thread scheduling
sychronization.
- Use the per-process spinlock rather than the sched_lock for per-process
scheduling synchronization.
- Move some common code into thread_suspend_switch() to handle the
mechanics of suspending a thread. The locking here is incredibly
convoluted and should be simplified.
Tested by: kris, current@
Tested on: i386, amd64, ULE, 4BSD, libthr, libkse, PREEMPTION, etc.
Discussed with: kris, attilio, kmacy, jhb, julian, bde (small parts each)
2007-06-04 23:52:24 +00:00
|
|
|
thread_lock(td2);
|
2008-03-21 08:23:25 +00:00
|
|
|
td2->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK;
|
2006-02-13 03:16:55 +00:00
|
|
|
if ((TD_IS_SLEEPING(td2) || TD_IS_SWAPPED(td2)) &&
|
2009-07-14 22:52:46 +00:00
|
|
|
(td2->td_flags & TDF_SINTR)) {
|
|
|
|
if (td2->td_flags & TDF_SBDRY) {
|
2013-02-06 17:06:51 +00:00
|
|
|
/*
|
|
|
|
* Once a thread is asleep with
|
2016-06-28 16:41:50 +00:00
|
|
|
* TDF_SBDRY and without TDF_SERESTART
|
|
|
|
* or TDF_SEINTR set, it should never
|
2013-02-06 17:06:51 +00:00
|
|
|
* become suspended due to this check.
|
|
|
|
*/
|
|
|
|
KASSERT(!TD_IS_SUSPENDED(td2),
|
|
|
|
("thread with deferred stops suspended"));
|
2019-12-15 21:11:15 +00:00
|
|
|
if (TD_SBDRY_INTR(td2)) {
|
2016-07-03 18:19:48 +00:00
|
|
|
wakeup_swapper |= sleepq_abort(td2,
|
|
|
|
TD_SBDRY_ERRNO(td2));
|
2019-12-15 21:11:15 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else if (!TD_IS_SUSPENDED(td2))
|
2009-07-14 22:52:46 +00:00
|
|
|
thread_suspend_one(td2);
|
|
|
|
} else if (!TD_IS_SUSPENDED(td2)) {
|
2006-02-13 03:16:55 +00:00
|
|
|
if (sending || td != td2)
|
|
|
|
td2->td_flags |= TDF_ASTPENDING;
|
|
|
|
#ifdef SMP
|
|
|
|
if (TD_IS_RUNNING(td2) && td2 != td)
|
|
|
|
forward_signal(td2);
|
|
|
|
#endif
|
|
|
|
}
|
Commit 4/14 of sched_lock decomposition.
- Use thread_lock() rather than sched_lock for per-thread scheduling
sychronization.
- Use the per-process spinlock rather than the sched_lock for per-process
scheduling synchronization.
- Move some common code into thread_suspend_switch() to handle the
mechanics of suspending a thread. The locking here is incredibly
convoluted and should be simplified.
Tested by: kris, current@
Tested on: i386, amd64, ULE, 4BSD, libthr, libkse, PREEMPTION, etc.
Discussed with: kris, attilio, kmacy, jhb, julian, bde (small parts each)
2007-06-04 23:52:24 +00:00
|
|
|
thread_unlock(td2);
|
2006-02-13 03:16:55 +00:00
|
|
|
}
|
2016-06-28 16:41:50 +00:00
|
|
|
return (wakeup_swapper);
|
2006-02-13 03:16:55 +00:00
|
|
|
}
|
|
|
|
|
2017-02-20 15:53:16 +00:00
|
|
|
/*
|
|
|
|
* Stop the process for an event deemed interesting to the debugger. If si is
|
|
|
|
* non-NULL, this is a signal exchange; the new signal requested by the
|
|
|
|
* debugger will be returned for handling. If si is NULL, this is some other
|
|
|
|
* type of interesting event. The debugger may request a signal be delivered in
|
|
|
|
* that case as well, however it will be deferred until it can be handled.
|
|
|
|
*/
|
Add code to support debugging threaded process.
1. Add tm_lwpid into kse_thr_mailbox to indicate which kernel
thread current user thread is running on. Add tm_dflags into
kse_thr_mailbox, the flags is written by debugger, it tells
UTS and kernel what should be done when the process is being
debugged, current, there two flags TMDF_SSTEP and TMDF_DONOTRUNUSER.
TMDF_SSTEP is used to tell kernel to turn on single stepping,
or turn off if it is not set.
TMDF_DONOTRUNUSER is used to tell kernel to schedule upcall
whenever possible, to UTS, it means do not run the user thread
until debugger clears it, this behaviour is necessary because
gdb wants to resume only one thread when the thread's pc is
at a breakpoint, and thread needs to go forward, in order to
avoid other threads sneak pass the breakpoints, it needs to remove
breakpoint, only wants one thread to go. Also, add km_lwp to
kse_mailbox, the lwp id is copied to kse_thr_mailbox at context
switch time when process is not being debugged, so when process
is attached, debugger can map kernel thread to user thread.
2. Add p_xthread to proc strcuture and td_xsig to thread structure.
p_xthread is used by a thread when it wants to report event
to debugger, every thread can set the pointer, especially, when
it is used in ptracestop, it is the last thread reporting event
will win the race. Every thread has a td_xsig to exchange signal
with debugger, thread uses TDF_XSIG flag to indicate it is reporting
signal to debugger, if the flag is not cleared, thread will keep
retrying until it is cleared by debugger, p_xthread may be
used by debugger to indicate CURRENT thread. The p_xstat is still
in proc structure to keep wait() to work, in future, we may
just use td_xsig.
3. Add TDF_DBSUSPEND flag, the flag is used by debugger to suspend
a thread. When process stops, debugger can set the flag for
thread, thread will check the flag in thread_suspend_check,
enters a loop, unless it is cleared by debugger, process is
detached or process is existing. The flag is also checked in
ptracestop, so debugger can temporarily suspend a thread even
if the thread wants to exchange signal.
4. Current, in ptrace, we always resume all threads, but if a thread
has already a TDF_DBSUSPEND flag set by debugger, it won't run.
Encouraged by: marcel, julian, deischen
2004-07-13 07:20:10 +00:00
|
|
|
int
|
2017-02-20 15:53:16 +00:00
|
|
|
ptracestop(struct thread *td, int sig, ksiginfo_t *si)
|
2003-09-26 15:09:46 +00:00
|
|
|
{
|
|
|
|
struct proc *p = td->td_proc;
|
2017-02-20 15:53:16 +00:00
|
|
|
struct thread *td2;
|
|
|
|
ksiginfo_t ksi;
|
2003-09-26 15:09:46 +00:00
|
|
|
|
2004-01-29 00:58:21 +00:00
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
2012-09-13 15:51:18 +00:00
|
|
|
KASSERT(!(p->p_flag & P_WEXIT), ("Stopping exiting process"));
|
2003-09-26 15:09:46 +00:00
|
|
|
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK,
|
2007-03-21 21:20:51 +00:00
|
|
|
&p->p_mtx.lock_object, "Stopping for traced signal");
|
2003-09-26 15:09:46 +00:00
|
|
|
|
Add code to support debugging threaded process.
1. Add tm_lwpid into kse_thr_mailbox to indicate which kernel
thread current user thread is running on. Add tm_dflags into
kse_thr_mailbox, the flags is written by debugger, it tells
UTS and kernel what should be done when the process is being
debugged, current, there two flags TMDF_SSTEP and TMDF_DONOTRUNUSER.
TMDF_SSTEP is used to tell kernel to turn on single stepping,
or turn off if it is not set.
TMDF_DONOTRUNUSER is used to tell kernel to schedule upcall
whenever possible, to UTS, it means do not run the user thread
until debugger clears it, this behaviour is necessary because
gdb wants to resume only one thread when the thread's pc is
at a breakpoint, and thread needs to go forward, in order to
avoid other threads sneak pass the breakpoints, it needs to remove
breakpoint, only wants one thread to go. Also, add km_lwp to
kse_mailbox, the lwp id is copied to kse_thr_mailbox at context
switch time when process is not being debugged, so when process
is attached, debugger can map kernel thread to user thread.
2. Add p_xthread to proc strcuture and td_xsig to thread structure.
p_xthread is used by a thread when it wants to report event
to debugger, every thread can set the pointer, especially, when
it is used in ptracestop, it is the last thread reporting event
will win the race. Every thread has a td_xsig to exchange signal
with debugger, thread uses TDF_XSIG flag to indicate it is reporting
signal to debugger, if the flag is not cleared, thread will keep
retrying until it is cleared by debugger, p_xthread may be
used by debugger to indicate CURRENT thread. The p_xstat is still
in proc structure to keep wait() to work, in future, we may
just use td_xsig.
3. Add TDF_DBSUSPEND flag, the flag is used by debugger to suspend
a thread. When process stops, debugger can set the flag for
thread, thread will check the flag in thread_suspend_check,
enters a loop, unless it is cleared by debugger, process is
detached or process is existing. The flag is also checked in
ptracestop, so debugger can temporarily suspend a thread even
if the thread wants to exchange signal.
4. Current, in ptrace, we always resume all threads, but if a thread
has already a TDF_DBSUSPEND flag set by debugger, it won't run.
Encouraged by: marcel, julian, deischen
2004-07-13 07:20:10 +00:00
|
|
|
td->td_xsig = sig;
|
2017-02-20 15:53:16 +00:00
|
|
|
|
|
|
|
if (si == NULL || (si->ksi_flags & KSI_PTRACE) == 0) {
|
|
|
|
td->td_dbgflags |= TDB_XSIG;
|
|
|
|
CTR4(KTR_PTRACE, "ptracestop: tid %d (pid %d) flags %#x sig %d",
|
|
|
|
td->td_tid, p->p_pid, td->td_dbgflags, sig);
|
|
|
|
PROC_SLOCK(p);
|
|
|
|
while ((p->p_flag & P_TRACED) && (td->td_dbgflags & TDB_XSIG)) {
|
|
|
|
if (P_KILLED(p)) {
|
|
|
|
/*
|
|
|
|
* Ensure that, if we've been PT_KILLed, the
|
|
|
|
* exit status reflects that. Another thread
|
|
|
|
* may also be in ptracestop(), having just
|
|
|
|
* received the SIGKILL, but this thread was
|
|
|
|
* unsuspended first.
|
|
|
|
*/
|
|
|
|
td->td_dbgflags &= ~TDB_XSIG;
|
|
|
|
td->td_xsig = SIGKILL;
|
|
|
|
p->p_ptevents = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (p->p_flag & P_SINGLE_EXIT &&
|
|
|
|
!(td->td_dbgflags & TDB_EXIT)) {
|
|
|
|
/*
|
|
|
|
* Ignore ptrace stops except for thread exit
|
|
|
|
* events when the process exits.
|
|
|
|
*/
|
|
|
|
td->td_dbgflags &= ~TDB_XSIG;
|
|
|
|
PROC_SUNLOCK(p);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2015-12-29 23:25:26 +00:00
|
|
|
/*
|
2017-02-20 15:53:16 +00:00
|
|
|
* Make wait(2) work. Ensure that right after the
|
|
|
|
* attach, the thread which was decided to become the
|
|
|
|
* leader of attach gets reported to the waiter.
|
|
|
|
* Otherwise, just avoid overwriting another thread's
|
|
|
|
* assignment to p_xthread. If another thread has
|
|
|
|
* already set p_xthread, the current thread will get
|
|
|
|
* a chance to report itself upon the next iteration.
|
2015-12-29 23:25:26 +00:00
|
|
|
*/
|
2017-02-20 15:53:16 +00:00
|
|
|
if ((td->td_dbgflags & TDB_FSTP) != 0 ||
|
|
|
|
((p->p_flag2 & P2_PTRACE_FSTP) == 0 &&
|
|
|
|
p->p_xthread == NULL)) {
|
|
|
|
p->p_xsig = sig;
|
|
|
|
p->p_xthread = td;
|
2019-05-29 14:05:27 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If we are on sleepqueue already,
|
|
|
|
* let sleepqueue code decide if it
|
|
|
|
* needs to go sleep after attach.
|
|
|
|
*/
|
|
|
|
if (td->td_wchan == NULL)
|
|
|
|
td->td_dbgflags &= ~TDB_FSTP;
|
|
|
|
|
2017-02-20 15:53:16 +00:00
|
|
|
p->p_flag2 &= ~P2_PTRACE_FSTP;
|
|
|
|
p->p_flag |= P_STOPPED_SIG | P_STOPPED_TRACE;
|
|
|
|
sig_suspend_threads(td, p, 0);
|
|
|
|
}
|
|
|
|
if ((td->td_dbgflags & TDB_STOPATFORK) != 0) {
|
|
|
|
td->td_dbgflags &= ~TDB_STOPATFORK;
|
|
|
|
}
|
|
|
|
stopme:
|
|
|
|
thread_suspend_switch(td, p);
|
|
|
|
if (p->p_xthread == td)
|
|
|
|
p->p_xthread = NULL;
|
|
|
|
if (!(p->p_flag & P_TRACED))
|
|
|
|
break;
|
|
|
|
if (td->td_dbgflags & TDB_SUSPEND) {
|
|
|
|
if (p->p_flag & P_SINGLE_EXIT)
|
|
|
|
break;
|
|
|
|
goto stopme;
|
|
|
|
}
|
Add code to support debugging threaded process.
1. Add tm_lwpid into kse_thr_mailbox to indicate which kernel
thread current user thread is running on. Add tm_dflags into
kse_thr_mailbox, the flags is written by debugger, it tells
UTS and kernel what should be done when the process is being
debugged, current, there two flags TMDF_SSTEP and TMDF_DONOTRUNUSER.
TMDF_SSTEP is used to tell kernel to turn on single stepping,
or turn off if it is not set.
TMDF_DONOTRUNUSER is used to tell kernel to schedule upcall
whenever possible, to UTS, it means do not run the user thread
until debugger clears it, this behaviour is necessary because
gdb wants to resume only one thread when the thread's pc is
at a breakpoint, and thread needs to go forward, in order to
avoid other threads sneak pass the breakpoints, it needs to remove
breakpoint, only wants one thread to go. Also, add km_lwp to
kse_mailbox, the lwp id is copied to kse_thr_mailbox at context
switch time when process is not being debugged, so when process
is attached, debugger can map kernel thread to user thread.
2. Add p_xthread to proc strcuture and td_xsig to thread structure.
p_xthread is used by a thread when it wants to report event
to debugger, every thread can set the pointer, especially, when
it is used in ptracestop, it is the last thread reporting event
will win the race. Every thread has a td_xsig to exchange signal
with debugger, thread uses TDF_XSIG flag to indicate it is reporting
signal to debugger, if the flag is not cleared, thread will keep
retrying until it is cleared by debugger, p_xthread may be
used by debugger to indicate CURRENT thread. The p_xstat is still
in proc structure to keep wait() to work, in future, we may
just use td_xsig.
3. Add TDF_DBSUSPEND flag, the flag is used by debugger to suspend
a thread. When process stops, debugger can set the flag for
thread, thread will check the flag in thread_suspend_check,
enters a loop, unless it is cleared by debugger, process is
detached or process is existing. The flag is also checked in
ptracestop, so debugger can temporarily suspend a thread even
if the thread wants to exchange signal.
4. Current, in ptrace, we always resume all threads, but if a thread
has already a TDF_DBSUSPEND flag set by debugger, it won't run.
Encouraged by: marcel, julian, deischen
2004-07-13 07:20:10 +00:00
|
|
|
}
|
2017-02-20 15:53:16 +00:00
|
|
|
PROC_SUNLOCK(p);
|
|
|
|
}
|
When a debugger attaches to the process, SIGSTOP is sent to the
target. Due to a way issignal() selects the next signal to deliver
and report, if the simultaneous or already pending another signal
exists, that signal might be reported by the next waitpid(2) call.
This causes minor annoyance for debuggers, which must be prepared to
take any signal as the first event, then filter SIGSTOP later.
More importantly, for tools like gcore(1), which attach and then
detach without processing events, SIGSTOP might leak to be delivered
after PT_DETACH. This results in the process being unintentionally
stopped after detach, which is fatal for automatic tools.
The solution is to force SIGSTOP to be the first signal reported after
the attach. Attach code is modified to set P2_PTRACE_FSTP to indicate
that the attaching ritual was not yet finished, and issignal() prefers
SIGSTOP in that condition. Also, the thread which handles
P2_PTRACE_FSTP is made to guarantee to own p_xthread during the first
waitpid(2). All that ensures that SIGSTOP is consumed first.
Additionally, if P2_PTRACE_FSTP is still set on detach, which means
that waitpid(2) was not called at all, SIGSTOP is removed from the
queue, ensuring that the process is resumed on detach.
In issignal(), when acting on STOPing signals, remove the signal from
queue before suspending. Otherwise parallel attach could result in
ptracestop() acting on that STOP as if it was the STOP signal from the
attach. Then SIGSTOP from attach leaks again.
As a minor refactoring, some bits of the common attach code is moved
to new helper proc_set_traced().
Reported by: markj
Reviewed by: jhb, markj
Tested by: pho
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Differential revision: https://reviews.freebsd.org/D7256
2016-07-28 08:41:13 +00:00
|
|
|
|
2017-02-20 15:53:16 +00:00
|
|
|
if (si != NULL && sig == td->td_xsig) {
|
|
|
|
/* Parent wants us to take the original signal unchanged. */
|
|
|
|
si->ksi_flags |= KSI_HEAD;
|
|
|
|
if (sigqueue_add(&td->td_sigqueue, sig, si) != 0)
|
|
|
|
si->ksi_signo = 0;
|
|
|
|
} else if (td->td_xsig != 0) {
|
Add code to support debugging threaded process.
1. Add tm_lwpid into kse_thr_mailbox to indicate which kernel
thread current user thread is running on. Add tm_dflags into
kse_thr_mailbox, the flags is written by debugger, it tells
UTS and kernel what should be done when the process is being
debugged, current, there two flags TMDF_SSTEP and TMDF_DONOTRUNUSER.
TMDF_SSTEP is used to tell kernel to turn on single stepping,
or turn off if it is not set.
TMDF_DONOTRUNUSER is used to tell kernel to schedule upcall
whenever possible, to UTS, it means do not run the user thread
until debugger clears it, this behaviour is necessary because
gdb wants to resume only one thread when the thread's pc is
at a breakpoint, and thread needs to go forward, in order to
avoid other threads sneak pass the breakpoints, it needs to remove
breakpoint, only wants one thread to go. Also, add km_lwp to
kse_mailbox, the lwp id is copied to kse_thr_mailbox at context
switch time when process is not being debugged, so when process
is attached, debugger can map kernel thread to user thread.
2. Add p_xthread to proc strcuture and td_xsig to thread structure.
p_xthread is used by a thread when it wants to report event
to debugger, every thread can set the pointer, especially, when
it is used in ptracestop, it is the last thread reporting event
will win the race. Every thread has a td_xsig to exchange signal
with debugger, thread uses TDF_XSIG flag to indicate it is reporting
signal to debugger, if the flag is not cleared, thread will keep
retrying until it is cleared by debugger, p_xthread may be
used by debugger to indicate CURRENT thread. The p_xstat is still
in proc structure to keep wait() to work, in future, we may
just use td_xsig.
3. Add TDF_DBSUSPEND flag, the flag is used by debugger to suspend
a thread. When process stops, debugger can set the flag for
thread, thread will check the flag in thread_suspend_check,
enters a loop, unless it is cleared by debugger, process is
detached or process is existing. The flag is also checked in
ptracestop, so debugger can temporarily suspend a thread even
if the thread wants to exchange signal.
4. Current, in ptrace, we always resume all threads, but if a thread
has already a TDF_DBSUSPEND flag set by debugger, it won't run.
Encouraged by: marcel, julian, deischen
2004-07-13 07:20:10 +00:00
|
|
|
/*
|
2017-02-20 15:53:16 +00:00
|
|
|
* If parent wants us to take a new signal, then it will leave
|
|
|
|
* it in td->td_xsig; otherwise we just look for signals again.
|
Add code to support debugging threaded process.
1. Add tm_lwpid into kse_thr_mailbox to indicate which kernel
thread current user thread is running on. Add tm_dflags into
kse_thr_mailbox, the flags is written by debugger, it tells
UTS and kernel what should be done when the process is being
debugged, current, there two flags TMDF_SSTEP and TMDF_DONOTRUNUSER.
TMDF_SSTEP is used to tell kernel to turn on single stepping,
or turn off if it is not set.
TMDF_DONOTRUNUSER is used to tell kernel to schedule upcall
whenever possible, to UTS, it means do not run the user thread
until debugger clears it, this behaviour is necessary because
gdb wants to resume only one thread when the thread's pc is
at a breakpoint, and thread needs to go forward, in order to
avoid other threads sneak pass the breakpoints, it needs to remove
breakpoint, only wants one thread to go. Also, add km_lwp to
kse_mailbox, the lwp id is copied to kse_thr_mailbox at context
switch time when process is not being debugged, so when process
is attached, debugger can map kernel thread to user thread.
2. Add p_xthread to proc strcuture and td_xsig to thread structure.
p_xthread is used by a thread when it wants to report event
to debugger, every thread can set the pointer, especially, when
it is used in ptracestop, it is the last thread reporting event
will win the race. Every thread has a td_xsig to exchange signal
with debugger, thread uses TDF_XSIG flag to indicate it is reporting
signal to debugger, if the flag is not cleared, thread will keep
retrying until it is cleared by debugger, p_xthread may be
used by debugger to indicate CURRENT thread. The p_xstat is still
in proc structure to keep wait() to work, in future, we may
just use td_xsig.
3. Add TDF_DBSUSPEND flag, the flag is used by debugger to suspend
a thread. When process stops, debugger can set the flag for
thread, thread will check the flag in thread_suspend_check,
enters a loop, unless it is cleared by debugger, process is
detached or process is existing. The flag is also checked in
ptracestop, so debugger can temporarily suspend a thread even
if the thread wants to exchange signal.
4. Current, in ptrace, we always resume all threads, but if a thread
has already a TDF_DBSUSPEND flag set by debugger, it won't run.
Encouraged by: marcel, julian, deischen
2004-07-13 07:20:10 +00:00
|
|
|
*/
|
2017-02-20 15:53:16 +00:00
|
|
|
ksiginfo_init(&ksi);
|
|
|
|
ksi.ksi_signo = td->td_xsig;
|
|
|
|
ksi.ksi_flags |= KSI_PTRACE;
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
td2 = sigtd(p, td->td_xsig, false);
|
2017-02-20 15:53:16 +00:00
|
|
|
tdsendsignal(p, td2, td->td_xsig, &ksi);
|
|
|
|
if (td != td2)
|
|
|
|
return (0);
|
Add code to support debugging threaded process.
1. Add tm_lwpid into kse_thr_mailbox to indicate which kernel
thread current user thread is running on. Add tm_dflags into
kse_thr_mailbox, the flags is written by debugger, it tells
UTS and kernel what should be done when the process is being
debugged, current, there two flags TMDF_SSTEP and TMDF_DONOTRUNUSER.
TMDF_SSTEP is used to tell kernel to turn on single stepping,
or turn off if it is not set.
TMDF_DONOTRUNUSER is used to tell kernel to schedule upcall
whenever possible, to UTS, it means do not run the user thread
until debugger clears it, this behaviour is necessary because
gdb wants to resume only one thread when the thread's pc is
at a breakpoint, and thread needs to go forward, in order to
avoid other threads sneak pass the breakpoints, it needs to remove
breakpoint, only wants one thread to go. Also, add km_lwp to
kse_mailbox, the lwp id is copied to kse_thr_mailbox at context
switch time when process is not being debugged, so when process
is attached, debugger can map kernel thread to user thread.
2. Add p_xthread to proc strcuture and td_xsig to thread structure.
p_xthread is used by a thread when it wants to report event
to debugger, every thread can set the pointer, especially, when
it is used in ptracestop, it is the last thread reporting event
will win the race. Every thread has a td_xsig to exchange signal
with debugger, thread uses TDF_XSIG flag to indicate it is reporting
signal to debugger, if the flag is not cleared, thread will keep
retrying until it is cleared by debugger, p_xthread may be
used by debugger to indicate CURRENT thread. The p_xstat is still
in proc structure to keep wait() to work, in future, we may
just use td_xsig.
3. Add TDF_DBSUSPEND flag, the flag is used by debugger to suspend
a thread. When process stops, debugger can set the flag for
thread, thread will check the flag in thread_suspend_check,
enters a loop, unless it is cleared by debugger, process is
detached or process is existing. The flag is also checked in
ptracestop, so debugger can temporarily suspend a thread even
if the thread wants to exchange signal.
4. Current, in ptrace, we always resume all threads, but if a thread
has already a TDF_DBSUSPEND flag set by debugger, it won't run.
Encouraged by: marcel, julian, deischen
2004-07-13 07:20:10 +00:00
|
|
|
}
|
2017-02-20 15:53:16 +00:00
|
|
|
|
Add code to support debugging threaded process.
1. Add tm_lwpid into kse_thr_mailbox to indicate which kernel
thread current user thread is running on. Add tm_dflags into
kse_thr_mailbox, the flags is written by debugger, it tells
UTS and kernel what should be done when the process is being
debugged, current, there two flags TMDF_SSTEP and TMDF_DONOTRUNUSER.
TMDF_SSTEP is used to tell kernel to turn on single stepping,
or turn off if it is not set.
TMDF_DONOTRUNUSER is used to tell kernel to schedule upcall
whenever possible, to UTS, it means do not run the user thread
until debugger clears it, this behaviour is necessary because
gdb wants to resume only one thread when the thread's pc is
at a breakpoint, and thread needs to go forward, in order to
avoid other threads sneak pass the breakpoints, it needs to remove
breakpoint, only wants one thread to go. Also, add km_lwp to
kse_mailbox, the lwp id is copied to kse_thr_mailbox at context
switch time when process is not being debugged, so when process
is attached, debugger can map kernel thread to user thread.
2. Add p_xthread to proc strcuture and td_xsig to thread structure.
p_xthread is used by a thread when it wants to report event
to debugger, every thread can set the pointer, especially, when
it is used in ptracestop, it is the last thread reporting event
will win the race. Every thread has a td_xsig to exchange signal
with debugger, thread uses TDF_XSIG flag to indicate it is reporting
signal to debugger, if the flag is not cleared, thread will keep
retrying until it is cleared by debugger, p_xthread may be
used by debugger to indicate CURRENT thread. The p_xstat is still
in proc structure to keep wait() to work, in future, we may
just use td_xsig.
3. Add TDF_DBSUSPEND flag, the flag is used by debugger to suspend
a thread. When process stops, debugger can set the flag for
thread, thread will check the flag in thread_suspend_check,
enters a loop, unless it is cleared by debugger, process is
detached or process is existing. The flag is also checked in
ptracestop, so debugger can temporarily suspend a thread even
if the thread wants to exchange signal.
4. Current, in ptrace, we always resume all threads, but if a thread
has already a TDF_DBSUSPEND flag set by debugger, it won't run.
Encouraged by: marcel, julian, deischen
2004-07-13 07:20:10 +00:00
|
|
|
return (td->td_xsig);
|
2003-09-26 15:09:46 +00:00
|
|
|
}
|
|
|
|
|
2020-03-10 20:04:38 +00:00
|
|
|
static void
|
2009-10-30 10:10:39 +00:00
|
|
|
reschedule_signals(struct proc *p, sigset_t block, int flags)
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
{
|
|
|
|
struct sigacts *ps;
|
|
|
|
struct thread *td;
|
2010-10-14 08:01:33 +00:00
|
|
|
int sig;
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
bool fastblk, pslocked;
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
|
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
2014-11-28 10:20:00 +00:00
|
|
|
ps = p->p_sigacts;
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
pslocked = (flags & SIGPROCMASK_PS_LOCKED) != 0;
|
|
|
|
mtx_assert(&ps->ps_mtx, pslocked ? MA_OWNED : MA_NOTOWNED);
|
2010-10-14 08:01:33 +00:00
|
|
|
if (SIGISEMPTY(p->p_siglist))
|
|
|
|
return;
|
|
|
|
SIGSETAND(block, p->p_siglist);
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
fastblk = (flags & SIGPROCMASK_FASTBLK) != 0;
|
2010-10-14 08:01:33 +00:00
|
|
|
while ((sig = sig_ffs(&block)) != 0) {
|
|
|
|
SIGDELSET(block, sig);
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
td = sigtd(p, sig, fastblk);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If sigtd() selected us despite sigfastblock is
|
|
|
|
* blocking, do not activate AST or wake us, to avoid
|
|
|
|
* loop in AST handler.
|
|
|
|
*/
|
|
|
|
if (fastblk && td == curthread)
|
|
|
|
continue;
|
|
|
|
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
signotify(td);
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
if (!pslocked)
|
2009-10-30 10:10:39 +00:00
|
|
|
mtx_lock(&ps->ps_mtx);
|
2017-05-12 15:34:59 +00:00
|
|
|
if (p->p_flag & P_TRACED ||
|
|
|
|
(SIGISMEMBER(ps->ps_sigcatch, sig) &&
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
!SIGISMEMBER(td->td_sigmask, sig))) {
|
2010-10-14 08:01:33 +00:00
|
|
|
tdsigwakeup(td, sig, SIG_CATCH,
|
|
|
|
(SIGISMEMBER(ps->ps_sigintr, sig) ? EINTR :
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
ERESTART));
|
|
|
|
}
|
|
|
|
if (!pslocked)
|
2009-10-30 10:10:39 +00:00
|
|
|
mtx_unlock(&ps->ps_mtx);
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
tdsigcleanup(struct thread *td)
|
|
|
|
{
|
|
|
|
struct proc *p;
|
|
|
|
sigset_t unblocked;
|
|
|
|
|
|
|
|
p = td->td_proc;
|
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
|
|
|
|
|
|
|
sigqueue_flush(&td->td_sigqueue);
|
|
|
|
if (p->p_numthreads == 1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Since we cannot handle signals, notify signal post code
|
|
|
|
* about this by filling the sigmask.
|
|
|
|
*
|
|
|
|
* Also, if needed, wake up thread(s) that do not block the
|
|
|
|
* same signals as the exiting thread, since the thread might
|
|
|
|
* have been selected for delivery and woken up.
|
|
|
|
*/
|
|
|
|
SIGFILLSET(unblocked);
|
|
|
|
SIGSETNAND(unblocked, td->td_sigmask);
|
|
|
|
SIGFILLSET(td->td_sigmask);
|
2009-10-30 10:10:39 +00:00
|
|
|
reschedule_signals(p, unblocked, 0);
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-06-26 20:07:24 +00:00
|
|
|
static int
|
|
|
|
sigdeferstop_curr_flags(int cflags)
|
|
|
|
{
|
|
|
|
|
|
|
|
MPASS((cflags & (TDF_SEINTR | TDF_SERESTART)) == 0 ||
|
|
|
|
(cflags & TDF_SBDRY) != 0);
|
|
|
|
return (cflags & (TDF_SBDRY | TDF_SEINTR | TDF_SERESTART));
|
|
|
|
}
|
|
|
|
|
2013-02-21 19:02:50 +00:00
|
|
|
/*
|
2016-06-26 20:07:24 +00:00
|
|
|
* Defer the delivery of SIGSTOP for the current thread, according to
|
|
|
|
* the requested mode. Returns previous flags, which must be restored
|
|
|
|
* by sigallowstop().
|
|
|
|
*
|
|
|
|
* TDF_SBDRY, TDF_SEINTR, and TDF_SERESTART flags are only set and
|
|
|
|
* cleared by the current thread, which allow the lock-less read-only
|
|
|
|
* accesses below.
|
2013-02-21 19:02:50 +00:00
|
|
|
*/
|
|
|
|
int
|
2016-07-03 18:19:48 +00:00
|
|
|
sigdeferstop_impl(int mode)
|
2013-02-06 17:06:51 +00:00
|
|
|
{
|
2013-02-21 19:02:50 +00:00
|
|
|
struct thread *td;
|
2016-06-26 20:07:24 +00:00
|
|
|
int cflags, nflags;
|
2013-02-06 17:06:51 +00:00
|
|
|
|
2013-02-21 19:02:50 +00:00
|
|
|
td = curthread;
|
2016-06-26 20:07:24 +00:00
|
|
|
cflags = sigdeferstop_curr_flags(td->td_flags);
|
|
|
|
switch (mode) {
|
|
|
|
case SIGDEFERSTOP_NOP:
|
|
|
|
nflags = cflags;
|
|
|
|
break;
|
|
|
|
case SIGDEFERSTOP_OFF:
|
|
|
|
nflags = 0;
|
|
|
|
break;
|
|
|
|
case SIGDEFERSTOP_SILENT:
|
|
|
|
nflags = (cflags | TDF_SBDRY) & ~(TDF_SEINTR | TDF_SERESTART);
|
|
|
|
break;
|
|
|
|
case SIGDEFERSTOP_EINTR:
|
|
|
|
nflags = (cflags | TDF_SBDRY | TDF_SEINTR) & ~TDF_SERESTART;
|
|
|
|
break;
|
|
|
|
case SIGDEFERSTOP_ERESTART:
|
|
|
|
nflags = (cflags | TDF_SBDRY | TDF_SERESTART) & ~TDF_SEINTR;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
panic("sigdeferstop: invalid mode %x", mode);
|
|
|
|
break;
|
|
|
|
}
|
2016-07-03 18:19:48 +00:00
|
|
|
if (cflags == nflags)
|
|
|
|
return (SIGDEFERSTOP_VAL_NCHG);
|
|
|
|
thread_lock(td);
|
|
|
|
td->td_flags = (td->td_flags & ~cflags) | nflags;
|
|
|
|
thread_unlock(td);
|
2016-06-26 20:07:24 +00:00
|
|
|
return (cflags);
|
2013-02-06 17:06:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2016-06-26 20:07:24 +00:00
|
|
|
* Restores the STOP handling mode, typically permitting the delivery
|
|
|
|
* of SIGSTOP for the current thread. This does not immediately
|
|
|
|
* suspend if a stop was posted. Instead, the thread will suspend
|
|
|
|
* either via ast() or a subsequent interruptible sleep.
|
2013-02-06 17:06:51 +00:00
|
|
|
*/
|
2016-06-26 20:07:24 +00:00
|
|
|
void
|
2016-07-03 18:19:48 +00:00
|
|
|
sigallowstop_impl(int prev)
|
2013-02-06 17:06:51 +00:00
|
|
|
{
|
2013-02-21 19:02:50 +00:00
|
|
|
struct thread *td;
|
2016-06-26 20:07:24 +00:00
|
|
|
int cflags;
|
2013-02-06 17:06:51 +00:00
|
|
|
|
2016-07-03 18:19:48 +00:00
|
|
|
KASSERT(prev != SIGDEFERSTOP_VAL_NCHG, ("failed sigallowstop"));
|
2016-06-26 20:07:24 +00:00
|
|
|
KASSERT((prev & ~(TDF_SBDRY | TDF_SEINTR | TDF_SERESTART)) == 0,
|
|
|
|
("sigallowstop: incorrect previous mode %x", prev));
|
2013-02-21 19:02:50 +00:00
|
|
|
td = curthread;
|
2016-06-26 20:07:24 +00:00
|
|
|
cflags = sigdeferstop_curr_flags(td->td_flags);
|
|
|
|
if (cflags != prev) {
|
|
|
|
thread_lock(td);
|
|
|
|
td->td_flags = (td->td_flags & ~cflags) | prev;
|
|
|
|
thread_unlock(td);
|
|
|
|
}
|
2013-02-06 17:06:51 +00:00
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* If the current process has received a signal (should be caught or cause
|
|
|
|
* termination, should interrupt current syscall), return the signal number.
|
|
|
|
* Stop signals with default action are processed immediately, then cleared;
|
|
|
|
* they aren't returned. This is checked after each entry to the system for
|
|
|
|
* a syscall or trap (though this can usually be done without calling issignal
|
2002-05-29 23:44:32 +00:00
|
|
|
* by checking the pending signal masks in cursig.) The normal call
|
1994-05-24 10:09:53 +00:00
|
|
|
* sequence is
|
|
|
|
*
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
* while (sig = cursig(curthread))
|
1999-09-29 15:03:48 +00:00
|
|
|
* postsig(sig);
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2003-05-05 21:16:28 +00:00
|
|
|
static int
|
2013-03-18 17:23:58 +00:00
|
|
|
issignal(struct thread *td)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
struct proc *p;
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
struct sigacts *ps;
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
struct sigqueue *queue;
|
2003-03-31 22:49:17 +00:00
|
|
|
sigset_t sigpending;
|
2017-03-30 18:21:36 +00:00
|
|
|
ksiginfo_t ksi;
|
2020-04-01 19:22:09 +00:00
|
|
|
int prop, sig;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
Part 1 of KSE-III
The ability to schedule multiple threads per process
(one one cpu) by making ALL system calls optionally asynchronous.
to come: ia64 and power-pc patches, patches for gdb, test program (in tools)
Reviewed by: Almost everyone who counts
(at various times, peter, jhb, matt, alfred, mini, bernd,
and a cast of thousands)
NOTE: this is still Beta code, and contains lots of debugging stuff.
expect slight instability in signals..
2002-06-29 17:26:22 +00:00
|
|
|
p = td->td_proc;
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
ps = p->p_sigacts;
|
|
|
|
mtx_assert(&ps->ps_mtx, MA_OWNED);
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
1994-05-24 10:09:53 +00:00
|
|
|
for (;;) {
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sigpending = td->td_sigqueue.sq_signals;
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
SIGSETOR(sigpending, p->p_sigqueue.sq_signals);
|
2003-03-31 22:49:17 +00:00
|
|
|
SIGSETNAND(sigpending, td->td_sigmask);
|
|
|
|
|
2016-06-28 16:41:50 +00:00
|
|
|
if ((p->p_flag & P_PPWAIT) != 0 || (td->td_flags &
|
|
|
|
(TDF_SBDRY | TDF_SERESTART | TDF_SEINTR)) == TDF_SBDRY)
|
2003-03-31 22:49:17 +00:00
|
|
|
SIG_STOPSIGMASK(sigpending);
|
|
|
|
if (SIGISEMPTY(sigpending)) /* no signal to send */
|
1994-05-24 10:09:53 +00:00
|
|
|
return (0);
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do fast sigblock if requested by usermode. Since
|
|
|
|
* we do know that there was a signal pending at this
|
|
|
|
* point, set the FAST_SIGBLOCK_PEND as indicator for
|
|
|
|
* usermode to perform a dummy call to
|
|
|
|
* FAST_SIGBLOCK_UNBLOCK, which causes immediate
|
|
|
|
* delivery of postponed pending signal.
|
|
|
|
*/
|
|
|
|
if ((td->td_pflags & TDP_SIGFASTBLOCK) != 0) {
|
|
|
|
if (td->td_sigblock_val != 0)
|
|
|
|
SIGSETNAND(sigpending, fastblock_mask);
|
|
|
|
if (SIGISEMPTY(sigpending)) {
|
|
|
|
td->td_pflags |= TDP_SIGFASTPENDING;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
When a debugger attaches to the process, SIGSTOP is sent to the
target. Due to a way issignal() selects the next signal to deliver
and report, if the simultaneous or already pending another signal
exists, that signal might be reported by the next waitpid(2) call.
This causes minor annoyance for debuggers, which must be prepared to
take any signal as the first event, then filter SIGSTOP later.
More importantly, for tools like gcore(1), which attach and then
detach without processing events, SIGSTOP might leak to be delivered
after PT_DETACH. This results in the process being unintentionally
stopped after detach, which is fatal for automatic tools.
The solution is to force SIGSTOP to be the first signal reported after
the attach. Attach code is modified to set P2_PTRACE_FSTP to indicate
that the attaching ritual was not yet finished, and issignal() prefers
SIGSTOP in that condition. Also, the thread which handles
P2_PTRACE_FSTP is made to guarantee to own p_xthread during the first
waitpid(2). All that ensures that SIGSTOP is consumed first.
Additionally, if P2_PTRACE_FSTP is still set on detach, which means
that waitpid(2) was not called at all, SIGSTOP is removed from the
queue, ensuring that the process is resumed on detach.
In issignal(), when acting on STOPing signals, remove the signal from
queue before suspending. Otherwise parallel attach could result in
ptracestop() acting on that STOP as if it was the STOP signal from the
attach. Then SIGSTOP from attach leaks again.
As a minor refactoring, some bits of the common attach code is moved
to new helper proc_set_traced().
Reported by: markj
Reviewed by: jhb, markj
Tested by: pho
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Differential revision: https://reviews.freebsd.org/D7256
2016-07-28 08:41:13 +00:00
|
|
|
if ((p->p_flag & (P_TRACED | P_PPTRACE)) == P_TRACED &&
|
|
|
|
(p->p_flag2 & P2_PTRACE_FSTP) != 0 &&
|
|
|
|
SIGISMEMBER(sigpending, SIGSTOP)) {
|
|
|
|
/*
|
|
|
|
* If debugger just attached, always consume
|
|
|
|
* SIGSTOP from ptrace(PT_ATTACH) first, to
|
|
|
|
* execute the debugger attach ritual in
|
|
|
|
* order.
|
|
|
|
*/
|
|
|
|
sig = SIGSTOP;
|
|
|
|
td->td_dbgflags |= TDB_FSTP;
|
|
|
|
} else {
|
|
|
|
sig = sig_ffs(&sigpending);
|
|
|
|
}
|
1997-12-06 04:11:14 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* We should see pending but ignored signals
|
|
|
|
* only if P_TRACED was on when they were posted.
|
|
|
|
*/
|
2020-04-01 19:22:09 +00:00
|
|
|
if (SIGISMEMBER(ps->ps_sigignore, sig) &&
|
|
|
|
(p->p_flag & P_TRACED) == 0) {
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
sigqueue_delete(&td->td_sigqueue, sig);
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
sigqueue_delete(&p->p_sigqueue, sig);
|
1994-05-24 10:09:53 +00:00
|
|
|
continue;
|
|
|
|
}
|
When a debugger attaches to the process, SIGSTOP is sent to the
target. Due to a way issignal() selects the next signal to deliver
and report, if the simultaneous or already pending another signal
exists, that signal might be reported by the next waitpid(2) call.
This causes minor annoyance for debuggers, which must be prepared to
take any signal as the first event, then filter SIGSTOP later.
More importantly, for tools like gcore(1), which attach and then
detach without processing events, SIGSTOP might leak to be delivered
after PT_DETACH. This results in the process being unintentionally
stopped after detach, which is fatal for automatic tools.
The solution is to force SIGSTOP to be the first signal reported after
the attach. Attach code is modified to set P2_PTRACE_FSTP to indicate
that the attaching ritual was not yet finished, and issignal() prefers
SIGSTOP in that condition. Also, the thread which handles
P2_PTRACE_FSTP is made to guarantee to own p_xthread during the first
waitpid(2). All that ensures that SIGSTOP is consumed first.
Additionally, if P2_PTRACE_FSTP is still set on detach, which means
that waitpid(2) was not called at all, SIGSTOP is removed from the
queue, ensuring that the process is resumed on detach.
In issignal(), when acting on STOPing signals, remove the signal from
queue before suspending. Otherwise parallel attach could result in
ptracestop() acting on that STOP as if it was the STOP signal from the
attach. Then SIGSTOP from attach leaks again.
As a minor refactoring, some bits of the common attach code is moved
to new helper proc_set_traced().
Reported by: markj
Reviewed by: jhb, markj
Tested by: pho
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Differential revision: https://reviews.freebsd.org/D7256
2016-07-28 08:41:13 +00:00
|
|
|
if ((p->p_flag & (P_TRACED | P_PPTRACE)) == P_TRACED) {
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2002-05-09 04:13:41 +00:00
|
|
|
* If traced, always stop.
|
When traced process is about to receive the signal, the process is
stopped and debugger may modify or drop the signal. After the changes to
keep process-targeted signals on the process sigqueue, another thread
may note the old signal on the queue and act before the thread removes
changed or dropped signal from the process queue. Since process is
traced, it usually gets stopped. Or, if the same signal is delivered
while process was stopped, the thread may erronously remove it,
intending to remove the original signal.
Remove the signal from the queue before notifying the debugger. Restore
the siginfo to the head of sigqueue when signal is allowed to be
delivered to the debugee, using newly introduced KSI_HEAD ksiginfo_t
flag. This preserves required order of delivery. Always restore the
unchanged signal on the curthread sigqueue, not to the process queue,
since the thread is about to get it anyway, because sigmask cannot be
changed.
Handle failure of reinserting the siginfo into the queue by falling
back to sq_kill method, calling sigqueue_add with NULL ksi.
If debugger changed the signal to be delivered, use sigqueue_add()
with NULL ksi instead of only setting sq_signals bit.
Reported by: Gardner Bell <gbell72 rogers com>
Analyzed and first version of fix by: Tijl Coosemans <tijl coosemans org>
PR: 142757
Reviewed by: davidxu
MFC after: 2 weeks
2010-01-20 11:58:04 +00:00
|
|
|
* Remove old signal from queue before the stop.
|
|
|
|
* XXX shrug off debugger, it causes siginfo to
|
|
|
|
* be thrown away.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
When traced process is about to receive the signal, the process is
stopped and debugger may modify or drop the signal. After the changes to
keep process-targeted signals on the process sigqueue, another thread
may note the old signal on the queue and act before the thread removes
changed or dropped signal from the process queue. Since process is
traced, it usually gets stopped. Or, if the same signal is delivered
while process was stopped, the thread may erronously remove it,
intending to remove the original signal.
Remove the signal from the queue before notifying the debugger. Restore
the siginfo to the head of sigqueue when signal is allowed to be
delivered to the debugee, using newly introduced KSI_HEAD ksiginfo_t
flag. This preserves required order of delivery. Always restore the
unchanged signal on the curthread sigqueue, not to the process queue,
since the thread is about to get it anyway, because sigmask cannot be
changed.
Handle failure of reinserting the siginfo into the queue by falling
back to sq_kill method, calling sigqueue_add with NULL ksi.
If debugger changed the signal to be delivered, use sigqueue_add()
with NULL ksi instead of only setting sq_signals bit.
Reported by: Gardner Bell <gbell72 rogers com>
Analyzed and first version of fix by: Tijl Coosemans <tijl coosemans org>
PR: 142757
Reviewed by: davidxu
MFC after: 2 weeks
2010-01-20 11:58:04 +00:00
|
|
|
queue = &td->td_sigqueue;
|
2017-03-30 18:21:36 +00:00
|
|
|
ksiginfo_init(&ksi);
|
|
|
|
if (sigqueue_get(queue, sig, &ksi) == 0) {
|
When traced process is about to receive the signal, the process is
stopped and debugger may modify or drop the signal. After the changes to
keep process-targeted signals on the process sigqueue, another thread
may note the old signal on the queue and act before the thread removes
changed or dropped signal from the process queue. Since process is
traced, it usually gets stopped. Or, if the same signal is delivered
while process was stopped, the thread may erronously remove it,
intending to remove the original signal.
Remove the signal from the queue before notifying the debugger. Restore
the siginfo to the head of sigqueue when signal is allowed to be
delivered to the debugee, using newly introduced KSI_HEAD ksiginfo_t
flag. This preserves required order of delivery. Always restore the
unchanged signal on the curthread sigqueue, not to the process queue,
since the thread is about to get it anyway, because sigmask cannot be
changed.
Handle failure of reinserting the siginfo into the queue by falling
back to sq_kill method, calling sigqueue_add with NULL ksi.
If debugger changed the signal to be delivered, use sigqueue_add()
with NULL ksi instead of only setting sq_signals bit.
Reported by: Gardner Bell <gbell72 rogers com>
Analyzed and first version of fix by: Tijl Coosemans <tijl coosemans org>
PR: 142757
Reviewed by: davidxu
MFC after: 2 weeks
2010-01-20 11:58:04 +00:00
|
|
|
queue = &p->p_sigqueue;
|
2017-03-30 18:21:36 +00:00
|
|
|
sigqueue_get(queue, sig, &ksi);
|
When traced process is about to receive the signal, the process is
stopped and debugger may modify or drop the signal. After the changes to
keep process-targeted signals on the process sigqueue, another thread
may note the old signal on the queue and act before the thread removes
changed or dropped signal from the process queue. Since process is
traced, it usually gets stopped. Or, if the same signal is delivered
while process was stopped, the thread may erronously remove it,
intending to remove the original signal.
Remove the signal from the queue before notifying the debugger. Restore
the siginfo to the head of sigqueue when signal is allowed to be
delivered to the debugee, using newly introduced KSI_HEAD ksiginfo_t
flag. This preserves required order of delivery. Always restore the
unchanged signal on the curthread sigqueue, not to the process queue,
since the thread is about to get it anyway, because sigmask cannot be
changed.
Handle failure of reinserting the siginfo into the queue by falling
back to sq_kill method, calling sigqueue_add with NULL ksi.
If debugger changed the signal to be delivered, use sigqueue_add()
with NULL ksi instead of only setting sq_signals bit.
Reported by: Gardner Bell <gbell72 rogers com>
Analyzed and first version of fix by: Tijl Coosemans <tijl coosemans org>
PR: 142757
Reviewed by: davidxu
MFC after: 2 weeks
2010-01-20 11:58:04 +00:00
|
|
|
}
|
2017-03-30 18:21:36 +00:00
|
|
|
td->td_si = ksi.ksi_info;
|
When traced process is about to receive the signal, the process is
stopped and debugger may modify or drop the signal. After the changes to
keep process-targeted signals on the process sigqueue, another thread
may note the old signal on the queue and act before the thread removes
changed or dropped signal from the process queue. Since process is
traced, it usually gets stopped. Or, if the same signal is delivered
while process was stopped, the thread may erronously remove it,
intending to remove the original signal.
Remove the signal from the queue before notifying the debugger. Restore
the siginfo to the head of sigqueue when signal is allowed to be
delivered to the debugee, using newly introduced KSI_HEAD ksiginfo_t
flag. This preserves required order of delivery. Always restore the
unchanged signal on the curthread sigqueue, not to the process queue,
since the thread is about to get it anyway, because sigmask cannot be
changed.
Handle failure of reinserting the siginfo into the queue by falling
back to sq_kill method, calling sigqueue_add with NULL ksi.
If debugger changed the signal to be delivered, use sigqueue_add()
with NULL ksi instead of only setting sq_signals bit.
Reported by: Gardner Bell <gbell72 rogers com>
Analyzed and first version of fix by: Tijl Coosemans <tijl coosemans org>
PR: 142757
Reviewed by: davidxu
MFC after: 2 weeks
2010-01-20 11:58:04 +00:00
|
|
|
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_unlock(&ps->ps_mtx);
|
2017-03-30 18:21:36 +00:00
|
|
|
sig = ptracestop(td, sig, &ksi);
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_lock(&ps->ps_mtx);
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2018-12-10 19:39:24 +00:00
|
|
|
td->td_si.si_signo = 0;
|
|
|
|
|
2017-02-20 15:53:16 +00:00
|
|
|
/*
|
2017-10-16 20:21:51 +00:00
|
|
|
* Keep looking if the debugger discarded or
|
|
|
|
* replaced the signal.
|
2003-05-16 01:34:23 +00:00
|
|
|
*/
|
2017-10-16 20:21:51 +00:00
|
|
|
if (sig == 0)
|
2003-05-16 01:34:23 +00:00
|
|
|
continue;
|
2017-10-16 20:21:51 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the signal became masked, re-queue it.
|
|
|
|
*/
|
|
|
|
if (SIGISMEMBER(td->td_sigmask, sig)) {
|
|
|
|
ksi.ksi_flags |= KSI_HEAD;
|
|
|
|
sigqueue_add(&p->p_sigqueue, sig, &ksi);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the traced bit got turned off, requeue
|
|
|
|
* the signal and go back up to the top to
|
|
|
|
* rescan signals. This ensures that p_sig*
|
|
|
|
* and p_sigact are consistent.
|
|
|
|
*/
|
|
|
|
if ((p->p_flag & P_TRACED) == 0) {
|
|
|
|
ksi.ksi_flags |= KSI_HEAD;
|
|
|
|
sigqueue_add(queue, sig, &ksi);
|
|
|
|
continue;
|
|
|
|
}
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2003-05-16 01:34:23 +00:00
|
|
|
prop = sigprop(sig);
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Decide whether the signal should be returned.
|
|
|
|
* Return the signal's number, or fall through
|
|
|
|
* to clear it from the pending mask.
|
|
|
|
*/
|
2002-12-17 19:13:03 +00:00
|
|
|
switch ((intptr_t)p->p_sigacts->ps_sigact[_SIG_IDX(sig)]) {
|
|
|
|
case (intptr_t)SIG_DFL:
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Don't take default actions on system processes.
|
|
|
|
*/
|
|
|
|
if (p->p_pid <= 1) {
|
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
/*
|
|
|
|
* Are you sure you want to ignore SIGSEGV
|
|
|
|
* in init? XXX
|
|
|
|
*/
|
1994-10-10 01:00:49 +00:00
|
|
|
printf("Process (pid %lu) got signal %d\n",
|
1999-09-29 15:03:48 +00:00
|
|
|
(u_long)p->p_pid, sig);
|
1994-05-24 10:09:53 +00:00
|
|
|
#endif
|
|
|
|
break; /* == ignore */
|
|
|
|
}
|
|
|
|
/*
|
2017-03-07 13:41:01 +00:00
|
|
|
* If there is a pending stop signal to process with
|
|
|
|
* default action, stop here, then clear the signal.
|
|
|
|
* Traced or exiting processes should ignore stops.
|
|
|
|
* Additionally, a member of an orphaned process group
|
|
|
|
* should ignore tty stops.
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
2016-09-02 18:22:56 +00:00
|
|
|
if (prop & SIGPROP_STOP) {
|
2017-03-07 13:41:01 +00:00
|
|
|
if (p->p_flag &
|
|
|
|
(P_TRACED | P_WEXIT | P_SINGLE_EXIT) ||
|
2012-11-27 10:11:54 +00:00
|
|
|
(p->p_pgrp->pg_jobc == 0 &&
|
2016-09-02 18:22:56 +00:00
|
|
|
prop & SIGPROP_TTYSTOP))
|
1994-05-24 10:09:53 +00:00
|
|
|
break; /* == ignore */
|
2016-07-03 18:19:48 +00:00
|
|
|
if (TD_SBDRY_INTR(td)) {
|
|
|
|
KASSERT((td->td_flags & TDF_SBDRY) != 0,
|
|
|
|
("lost TDF_SBDRY"));
|
|
|
|
return (-1);
|
|
|
|
}
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_unlock(&ps->ps_mtx);
|
|
|
|
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK,
|
2007-03-21 21:20:51 +00:00
|
|
|
&p->p_mtx.lock_object, "Catching SIGSTOP");
|
When a debugger attaches to the process, SIGSTOP is sent to the
target. Due to a way issignal() selects the next signal to deliver
and report, if the simultaneous or already pending another signal
exists, that signal might be reported by the next waitpid(2) call.
This causes minor annoyance for debuggers, which must be prepared to
take any signal as the first event, then filter SIGSTOP later.
More importantly, for tools like gcore(1), which attach and then
detach without processing events, SIGSTOP might leak to be delivered
after PT_DETACH. This results in the process being unintentionally
stopped after detach, which is fatal for automatic tools.
The solution is to force SIGSTOP to be the first signal reported after
the attach. Attach code is modified to set P2_PTRACE_FSTP to indicate
that the attaching ritual was not yet finished, and issignal() prefers
SIGSTOP in that condition. Also, the thread which handles
P2_PTRACE_FSTP is made to guarantee to own p_xthread during the first
waitpid(2). All that ensures that SIGSTOP is consumed first.
Additionally, if P2_PTRACE_FSTP is still set on detach, which means
that waitpid(2) was not called at all, SIGSTOP is removed from the
queue, ensuring that the process is resumed on detach.
In issignal(), when acting on STOPing signals, remove the signal from
queue before suspending. Otherwise parallel attach could result in
ptracestop() acting on that STOP as if it was the STOP signal from the
attach. Then SIGSTOP from attach leaks again.
As a minor refactoring, some bits of the common attach code is moved
to new helper proc_set_traced().
Reported by: markj
Reviewed by: jhb, markj
Tested by: pho
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Differential revision: https://reviews.freebsd.org/D7256
2016-07-28 08:41:13 +00:00
|
|
|
sigqueue_delete(&td->td_sigqueue, sig);
|
|
|
|
sigqueue_delete(&p->p_sigqueue, sig);
|
2003-03-11 00:07:53 +00:00
|
|
|
p->p_flag |= P_STOPPED_SIG;
|
2015-07-18 09:02:50 +00:00
|
|
|
p->p_xsig = sig;
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SLOCK(p);
|
2006-02-13 03:16:55 +00:00
|
|
|
sig_suspend_threads(td, p, 0);
|
2014-12-13 16:18:29 +00:00
|
|
|
thread_suspend_switch(td, p);
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SUNLOCK(p);
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_lock(&ps->ps_mtx);
|
When a debugger attaches to the process, SIGSTOP is sent to the
target. Due to a way issignal() selects the next signal to deliver
and report, if the simultaneous or already pending another signal
exists, that signal might be reported by the next waitpid(2) call.
This causes minor annoyance for debuggers, which must be prepared to
take any signal as the first event, then filter SIGSTOP later.
More importantly, for tools like gcore(1), which attach and then
detach without processing events, SIGSTOP might leak to be delivered
after PT_DETACH. This results in the process being unintentionally
stopped after detach, which is fatal for automatic tools.
The solution is to force SIGSTOP to be the first signal reported after
the attach. Attach code is modified to set P2_PTRACE_FSTP to indicate
that the attaching ritual was not yet finished, and issignal() prefers
SIGSTOP in that condition. Also, the thread which handles
P2_PTRACE_FSTP is made to guarantee to own p_xthread during the first
waitpid(2). All that ensures that SIGSTOP is consumed first.
Additionally, if P2_PTRACE_FSTP is still set on detach, which means
that waitpid(2) was not called at all, SIGSTOP is removed from the
queue, ensuring that the process is resumed on detach.
In issignal(), when acting on STOPing signals, remove the signal from
queue before suspending. Otherwise parallel attach could result in
ptracestop() acting on that STOP as if it was the STOP signal from the
attach. Then SIGSTOP from attach leaks again.
As a minor refactoring, some bits of the common attach code is moved
to new helper proc_set_traced().
Reported by: markj
Reviewed by: jhb, markj
Tested by: pho
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Differential revision: https://reviews.freebsd.org/D7256
2016-07-28 08:41:13 +00:00
|
|
|
goto next;
|
2016-09-02 18:22:56 +00:00
|
|
|
} else if (prop & SIGPROP_IGNORE) {
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Except for SIGCONT, shouldn't get here.
|
|
|
|
* Default action is to ignore; drop it.
|
|
|
|
*/
|
|
|
|
break; /* == ignore */
|
|
|
|
} else
|
1999-09-29 15:03:48 +00:00
|
|
|
return (sig);
|
1994-05-24 10:09:53 +00:00
|
|
|
/*NOTREACHED*/
|
|
|
|
|
2002-12-17 19:13:03 +00:00
|
|
|
case (intptr_t)SIG_IGN:
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Masking above should prevent us ever trying
|
|
|
|
* to take action on an ignored signal other
|
|
|
|
* than SIGCONT, unless process is traced.
|
|
|
|
*/
|
2016-09-02 18:22:56 +00:00
|
|
|
if ((prop & SIGPROP_CONT) == 0 &&
|
1994-05-24 10:09:53 +00:00
|
|
|
(p->p_flag & P_TRACED) == 0)
|
|
|
|
printf("issignal\n");
|
|
|
|
break; /* == ignore */
|
|
|
|
|
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* This signal has an action, let
|
|
|
|
* postsig() process it.
|
|
|
|
*/
|
1999-09-29 15:03:48 +00:00
|
|
|
return (sig);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2012-11-27 10:11:54 +00:00
|
|
|
sigqueue_delete(&td->td_sigqueue, sig); /* take the signal! */
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
sigqueue_delete(&p->p_sigqueue, sig);
|
When a debugger attaches to the process, SIGSTOP is sent to the
target. Due to a way issignal() selects the next signal to deliver
and report, if the simultaneous or already pending another signal
exists, that signal might be reported by the next waitpid(2) call.
This causes minor annoyance for debuggers, which must be prepared to
take any signal as the first event, then filter SIGSTOP later.
More importantly, for tools like gcore(1), which attach and then
detach without processing events, SIGSTOP might leak to be delivered
after PT_DETACH. This results in the process being unintentionally
stopped after detach, which is fatal for automatic tools.
The solution is to force SIGSTOP to be the first signal reported after
the attach. Attach code is modified to set P2_PTRACE_FSTP to indicate
that the attaching ritual was not yet finished, and issignal() prefers
SIGSTOP in that condition. Also, the thread which handles
P2_PTRACE_FSTP is made to guarantee to own p_xthread during the first
waitpid(2). All that ensures that SIGSTOP is consumed first.
Additionally, if P2_PTRACE_FSTP is still set on detach, which means
that waitpid(2) was not called at all, SIGSTOP is removed from the
queue, ensuring that the process is resumed on detach.
In issignal(), when acting on STOPing signals, remove the signal from
queue before suspending. Otherwise parallel attach could result in
ptracestop() acting on that STOP as if it was the STOP signal from the
attach. Then SIGSTOP from attach leaks again.
As a minor refactoring, some bits of the common attach code is moved
to new helper proc_set_traced().
Reported by: markj
Reviewed by: jhb, markj
Tested by: pho
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Differential revision: https://reviews.freebsd.org/D7256
2016-07-28 08:41:13 +00:00
|
|
|
next:;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
2003-03-11 00:07:53 +00:00
|
|
|
void
|
|
|
|
thread_stopped(struct proc *p)
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
|
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SLOCK_ASSERT(p, MA_OWNED);
|
2003-03-11 00:07:53 +00:00
|
|
|
n = p->p_suspcount;
|
2006-02-23 05:50:55 +00:00
|
|
|
if (p == curproc)
|
2003-03-11 00:07:53 +00:00
|
|
|
n++;
|
|
|
|
if ((p->p_flag & P_STOPPED_SIG) && (n == p->p_numthreads)) {
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SUNLOCK(p);
|
2005-04-19 08:11:28 +00:00
|
|
|
p->p_flag &= ~P_WAITED;
|
2003-03-11 00:07:53 +00:00
|
|
|
PROC_LOCK(p->p_pptr);
|
2006-02-04 14:10:57 +00:00
|
|
|
childproc_stopped(p, (p->p_flag & P_TRACED) ?
|
|
|
|
CLD_TRAPPED : CLD_STOPPED);
|
2003-03-11 00:07:53 +00:00
|
|
|
PROC_UNLOCK(p->p_pptr);
|
2008-11-05 03:01:23 +00:00
|
|
|
PROC_SLOCK(p);
|
2003-03-11 00:07:53 +00:00
|
|
|
}
|
|
|
|
}
|
2012-11-27 10:11:54 +00:00
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Take the action for the specified signal
|
|
|
|
* from the current set of pending signals.
|
|
|
|
*/
|
In r198506, kern_sigsuspend() started doing cursig/postsig loop to make
sure that a signal was delivered to the thread before returning from
syscall. Signal delivery puts new return frame on the user stack, and
modifies trap frame to enter signal handler. As a consequence, syscall
return code sets EINTR as error return for signal frame, instead of the
syscall return.
Also, for ia64, due to different registers layout for those two kind of
frames, usermode sigsegfaulted when returned from signal handler.
Use newly-introduced cpu_set_syscall_retval(9) to set syscall result,
and return EJUSTRETURN from kern_sigsuspend() to prevent syscall return
code from modifying this frame [1].
Another issue is that pending SIGCONT might be cancelled by SIGSTOP,
causing postsig() not to deliver any catched signal [2]. Modify
postsig() to return 1 if signal was posted, and 0 otherwise, and use
this in the kern_sigsuspend loop.
Proposed by: marcel [1]
Noted by: davidxu [2]
Reviewed by: marcel, davidxu
MFC after: 1 month
2009-11-10 11:46:53 +00:00
|
|
|
int
|
2017-10-16 20:11:29 +00:00
|
|
|
postsig(int sig)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2017-10-16 20:11:29 +00:00
|
|
|
struct thread *td;
|
|
|
|
struct proc *p;
|
2001-03-07 02:59:54 +00:00
|
|
|
struct sigacts *ps;
|
1999-09-29 15:03:48 +00:00
|
|
|
sig_t action;
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
ksiginfo_t ksi;
|
2014-11-26 14:09:04 +00:00
|
|
|
sigset_t returnmask;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
1999-09-29 15:03:48 +00:00
|
|
|
KASSERT(sig != 0, ("postsig"));
|
1999-01-08 17:31:30 +00:00
|
|
|
|
2017-10-16 20:11:29 +00:00
|
|
|
td = curthread;
|
|
|
|
p = td->td_proc;
|
2001-06-22 23:02:37 +00:00
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
2001-03-07 02:59:54 +00:00
|
|
|
ps = p->p_sigacts;
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_assert(&ps->ps_mtx, MA_OWNED);
|
2005-10-23 04:12:26 +00:00
|
|
|
ksiginfo_init(&ksi);
|
Currently, when signal is delivered to the process and there is a thread
not blocking the signal, signal is placed on the thread sigqueue. If
the selected thread is in kernel executing thr_exit() or sigprocmask()
syscalls, then signal might be not delivered to usermode for arbitrary
amount of time, and for exiting thread it is lost.
Put process-directed signals to the process queue unconditionally,
selecting the thread to deliver the signal only by the thread returning
to usermode, since only then the thread can handle delivery of signal
reliably. For exiting thread or thread that has blocked some signals,
check whether the newly blocked signal is queued for the process, and
try to find a thread to wakeup for delivery, in reschedule_signal(). For
exiting thread, assume that all signals are blocked.
Change cursig() and postsig() to look both into the thread and process
signal queues. When there is a signal that thread returning to usermode
could consume, TDF_NEEDSIGCHK flag is not neccessary set now. Do
unlocked read of p_siglist and p_pendingcnt to check for queued signals.
Note that thread that has a signal unblocked might get spurious wakeup
and EINTR from the interruptible system call now, due to the possibility
of being selected by reschedule_signals(), while other thread returned
to usermode earlier and removed the signal from process queue. This
should not cause compliance issues, since the thread has not blocked a
signal and thus should be ready to receive it anyway.
Reported by: Justin Teller <justin.teller gmail com>
Reviewed by: davidxu, jilles
MFC after: 1 month
2009-10-11 16:49:30 +00:00
|
|
|
if (sigqueue_get(&td->td_sigqueue, sig, &ksi) == 0 &&
|
|
|
|
sigqueue_get(&p->p_sigqueue, sig, &ksi) == 0)
|
In r198506, kern_sigsuspend() started doing cursig/postsig loop to make
sure that a signal was delivered to the thread before returning from
syscall. Signal delivery puts new return frame on the user stack, and
modifies trap frame to enter signal handler. As a consequence, syscall
return code sets EINTR as error return for signal frame, instead of the
syscall return.
Also, for ia64, due to different registers layout for those two kind of
frames, usermode sigsegfaulted when returned from signal handler.
Use newly-introduced cpu_set_syscall_retval(9) to set syscall result,
and return EJUSTRETURN from kern_sigsuspend() to prevent syscall return
code from modifying this frame [1].
Another issue is that pending SIGCONT might be cancelled by SIGSTOP,
causing postsig() not to deliver any catched signal [2]. Modify
postsig() to return 1 if signal was posted, and 0 otherwise, and use
this in the kern_sigsuspend loop.
Proposed by: marcel [1]
Noted by: davidxu [2]
Reviewed by: marcel, davidxu
MFC after: 1 month
2009-11-10 11:46:53 +00:00
|
|
|
return (0);
|
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and
sendsig use discrete parameters, now they uses member fields of
ksiginfo_t structure. For sendsig, this change allows us to pass
POSIX realtime signal value to user code.
2. Remove cpu_thread_siginfo, it is no longer needed because we now always
generate ksiginfo_t data and feed it to libpthread.
3. Add p_sigqueue to proc structure to hold shared signals which were
blocked by all threads in the proc.
4. Add td_sigqueue to thread structure to hold all signals delivered to
thread.
5. i386 and amd64 now return POSIX standard si_code, other arches will
be fixed.
6. In this sigqueue implementation, pending signal set is kept as before,
an extra siginfo list holds additional siginfo_t data for signals.
kernel code uses psignal() still behavior as before, it won't be failed
even under memory pressure, only exception is when deleting a signal,
we should call sigqueue_delete to remove signal from sigqueue but
not SIGDELSET. Current there is no kernel code will deliver a signal
with additional data, so kernel should be as stable as before,
a ksiginfo can carry more information, for example, allow signal to
be delivered but throw away siginfo data if memory is not enough.
SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can
not be caught or masked.
The sigqueue() syscall allows user code to queue a signal to target
process, if resource is unavailable, EAGAIN will be returned as
specification said.
Just before thread exits, signal queue memory will be freed by
sigqueue_flush.
Current, all signals are allowed to be queued, not only realtime signals.
Earlier patch reviewed by: jhb, deischen
Tested on: i386, amd64
2005-10-14 12:43:47 +00:00
|
|
|
ksi.ksi_signo = sig;
|
2005-10-30 02:56:08 +00:00
|
|
|
if (ksi.ksi_code == SI_TIMER)
|
|
|
|
itimer_accept(p, ksi.ksi_timerid, &ksi);
|
1999-09-29 15:03:48 +00:00
|
|
|
action = ps->ps_sigact[_SIG_IDX(sig)];
|
1994-05-24 10:09:53 +00:00
|
|
|
#ifdef KTRACE
|
2002-06-07 05:43:02 +00:00
|
|
|
if (KTRPOINT(td, KTR_PSIG))
|
2003-06-09 17:38:32 +00:00
|
|
|
ktrpsig(sig, action, td->td_pflags & TDP_OLDMASK ?
|
2011-04-17 14:38:11 +00:00
|
|
|
&td->td_oldsigmask : &td->td_sigmask, ksi.ksi_code);
|
1994-05-24 10:09:53 +00:00
|
|
|
#endif
|
1997-12-06 04:11:14 +00:00
|
|
|
|
2006-10-26 21:42:22 +00:00
|
|
|
if (action == SIG_DFL) {
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Default action, where the default is to kill
|
|
|
|
* the process. (Other cases were ignored above.)
|
|
|
|
*/
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_unlock(&ps->ps_mtx);
|
2017-03-30 18:21:36 +00:00
|
|
|
proc_td_siginfo_capture(td, &ksi.ksi_info);
|
2001-09-12 08:38:13 +00:00
|
|
|
sigexit(td, sig);
|
1994-05-24 10:09:53 +00:00
|
|
|
/* NOTREACHED */
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* If we get here, the signal must be caught.
|
|
|
|
*/
|
2017-10-16 20:15:19 +00:00
|
|
|
KASSERT(action != SIG_IGN, ("postsig action %p", action));
|
|
|
|
KASSERT(!SIGISMEMBER(td->td_sigmask, sig),
|
|
|
|
("postsig action: blocked sig %d", sig));
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Set the new mask value and also defer further
|
1999-10-11 20:33:17 +00:00
|
|
|
* occurrences of this signal.
|
1994-05-24 10:09:53 +00:00
|
|
|
*
|
1999-10-11 20:33:17 +00:00
|
|
|
* Special case: user has done a sigsuspend. Here the
|
1994-05-24 10:09:53 +00:00
|
|
|
* current mask is not of interest, but rather the
|
1999-10-11 20:33:17 +00:00
|
|
|
* mask from before the sigsuspend is what we want
|
1994-05-24 10:09:53 +00:00
|
|
|
* restored after the signal processing is completed.
|
|
|
|
*/
|
2003-06-09 17:38:32 +00:00
|
|
|
if (td->td_pflags & TDP_OLDMASK) {
|
2003-03-31 22:49:17 +00:00
|
|
|
returnmask = td->td_oldsigmask;
|
2003-06-09 17:38:32 +00:00
|
|
|
td->td_pflags &= ~TDP_OLDMASK;
|
1994-05-24 10:09:53 +00:00
|
|
|
} else
|
2003-03-31 22:49:17 +00:00
|
|
|
returnmask = td->td_sigmask;
|
1999-09-29 15:03:48 +00:00
|
|
|
|
2009-02-26 15:51:54 +00:00
|
|
|
if (p->p_sig == sig) {
|
1998-12-19 02:55:34 +00:00
|
|
|
p->p_sig = 0;
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
2006-10-26 21:42:22 +00:00
|
|
|
(*p->p_sysent->sv_sendsig)(action, &ksi, &returnmask);
|
2014-11-26 14:09:04 +00:00
|
|
|
postsig_done(sig, td, ps);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
In r198506, kern_sigsuspend() started doing cursig/postsig loop to make
sure that a signal was delivered to the thread before returning from
syscall. Signal delivery puts new return frame on the user stack, and
modifies trap frame to enter signal handler. As a consequence, syscall
return code sets EINTR as error return for signal frame, instead of the
syscall return.
Also, for ia64, due to different registers layout for those two kind of
frames, usermode sigsegfaulted when returned from signal handler.
Use newly-introduced cpu_set_syscall_retval(9) to set syscall result,
and return EJUSTRETURN from kern_sigsuspend() to prevent syscall return
code from modifying this frame [1].
Another issue is that pending SIGCONT might be cancelled by SIGSTOP,
causing postsig() not to deliver any catched signal [2]. Modify
postsig() to return 1 if signal was posted, and 0 otherwise, and use
this in the kern_sigsuspend loop.
Proposed by: marcel [1]
Noted by: davidxu [2]
Reviewed by: marcel, davidxu
MFC after: 1 month
2009-11-10 11:46:53 +00:00
|
|
|
return (1);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
2020-10-04 16:30:05 +00:00
|
|
|
int
|
|
|
|
sig_ast_checksusp(struct thread *td)
|
|
|
|
{
|
|
|
|
struct proc *p;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
p = td->td_proc;
|
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
|
|
|
|
|
|
|
if ((td->td_flags & TDF_NEEDSUSPCHK) == 0)
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
ret = thread_suspend_check(1);
|
|
|
|
MPASS(ret == 0 || ret == EINTR || ret == ERESTART);
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
sig_ast_needsigchk(struct thread *td)
|
|
|
|
{
|
|
|
|
struct proc *p;
|
|
|
|
struct sigacts *ps;
|
|
|
|
int ret, sig;
|
|
|
|
|
|
|
|
p = td->td_proc;
|
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
|
|
|
|
|
|
|
if ((td->td_flags & TDF_NEEDSIGCHK) == 0)
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
ps = p->p_sigacts;
|
|
|
|
mtx_lock(&ps->ps_mtx);
|
|
|
|
sig = cursig(td);
|
|
|
|
if (sig == -1) {
|
|
|
|
mtx_unlock(&ps->ps_mtx);
|
|
|
|
KASSERT((td->td_flags & TDF_SBDRY) != 0, ("lost TDF_SBDRY"));
|
|
|
|
KASSERT(TD_SBDRY_INTR(td),
|
|
|
|
("lost TDF_SERESTART of TDF_SEINTR"));
|
|
|
|
KASSERT((td->td_flags & (TDF_SEINTR | TDF_SERESTART)) !=
|
|
|
|
(TDF_SEINTR | TDF_SERESTART),
|
|
|
|
("both TDF_SEINTR and TDF_SERESTART"));
|
|
|
|
ret = TD_SBDRY_ERRNO(td);
|
|
|
|
} else if (sig != 0) {
|
|
|
|
ret = SIGISMEMBER(ps->ps_sigintr, sig) ? EINTR : ERESTART;
|
|
|
|
mtx_unlock(&ps->ps_mtx);
|
|
|
|
} else {
|
|
|
|
mtx_unlock(&ps->ps_mtx);
|
|
|
|
ret = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do not go into sleep if this thread was the ptrace(2)
|
|
|
|
* attach leader. cursig() consumed SIGSTOP from PT_ATTACH,
|
|
|
|
* but we usually act on the signal by interrupting sleep, and
|
|
|
|
* should do that here as well.
|
|
|
|
*/
|
|
|
|
if ((td->td_dbgflags & TDB_FSTP) != 0) {
|
|
|
|
if (ret == 0)
|
|
|
|
ret = EINTR;
|
|
|
|
td->td_dbgflags &= ~TDB_FSTP;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
2020-10-04 16:33:42 +00:00
|
|
|
int
|
|
|
|
sig_intr(void)
|
|
|
|
{
|
|
|
|
struct thread *td;
|
|
|
|
struct proc *p;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
td = curthread;
|
2020-10-08 22:34:34 +00:00
|
|
|
if ((td->td_flags & (TDF_NEEDSIGCHK | TDF_NEEDSUSPCHK)) == 0)
|
|
|
|
return (0);
|
|
|
|
|
2020-10-04 16:33:42 +00:00
|
|
|
p = td->td_proc;
|
|
|
|
|
|
|
|
PROC_LOCK(p);
|
|
|
|
ret = sig_ast_checksusp(td);
|
|
|
|
if (ret == 0)
|
|
|
|
ret = sig_ast_needsigchk(td);
|
|
|
|
PROC_UNLOCK(p);
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
2018-08-04 20:45:43 +00:00
|
|
|
void
|
|
|
|
proc_wkilled(struct proc *p)
|
|
|
|
{
|
|
|
|
|
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
|
|
|
if ((p->p_flag & P_WKILLED) == 0) {
|
|
|
|
p->p_flag |= P_WKILLED;
|
|
|
|
/*
|
|
|
|
* Notify swapper that there is a process to swap in.
|
|
|
|
* The notification is racy, at worst it would take 10
|
|
|
|
* seconds for the swapper process to notice.
|
|
|
|
*/
|
|
|
|
if ((p->p_flag & (P_INMEM | P_SWAPPINGIN)) == 0)
|
|
|
|
wakeup(&proc0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
|
|
|
* Kill the current process for stated reason.
|
|
|
|
*/
|
1994-05-25 09:21:21 +00:00
|
|
|
void
|
2020-02-23 03:32:16 +00:00
|
|
|
killproc(struct proc *p, const char *why)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2001-05-15 23:13:58 +00:00
|
|
|
|
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
2012-11-27 10:15:58 +00:00
|
|
|
CTR3(KTR_PROC, "killproc: proc %p (pid %d, %s)", p, p->p_pid,
|
|
|
|
p->p_comm);
|
2018-12-29 14:48:51 +00:00
|
|
|
log(LOG_ERR, "pid %d (%s), jid %d, uid %d, was killed: %s\n",
|
2018-12-29 21:36:02 +00:00
|
|
|
p->p_pid, p->p_comm, p->p_ucred->cr_prison->pr_id,
|
2019-01-04 21:12:17 +00:00
|
|
|
p->p_ucred->cr_uid, why);
|
2018-08-04 20:45:43 +00:00
|
|
|
proc_wkilled(p);
|
2011-09-16 13:58:51 +00:00
|
|
|
kern_psignal(p, SIGKILL);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Force the current process to exit with the specified signal, dumping core
|
|
|
|
* if appropriate. We bypass the normal tests for masked and caught signals,
|
|
|
|
* allowing unrecoverable failures to terminate the process without changing
|
|
|
|
* signal state. Mark the accounting record with the signal termination.
|
|
|
|
* If dumping core, save the signal number for the debugger. Calls exit and
|
|
|
|
* does not return.
|
|
|
|
*/
|
1994-05-25 09:21:21 +00:00
|
|
|
void
|
2017-03-02 22:17:53 +00:00
|
|
|
sigexit(struct thread *td, int sig)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2001-09-12 08:38:13 +00:00
|
|
|
struct proc *p = td->td_proc;
|
1994-05-24 10:09:53 +00:00
|
|
|
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
1994-05-24 10:09:53 +00:00
|
|
|
p->p_acflag |= AXSIG;
|
2005-04-10 02:31:24 +00:00
|
|
|
/*
|
|
|
|
* We must be single-threading to generate a core dump. This
|
|
|
|
* ensures that the registers in the core file are up-to-date.
|
|
|
|
* Also, the ELF dump handler assumes that the thread list doesn't
|
|
|
|
* change out from under it.
|
|
|
|
*
|
|
|
|
* XXX If another thread attempts to single-thread before us
|
|
|
|
* (e.g. via fork()), we won't get a dump at all.
|
|
|
|
*/
|
2016-09-02 18:22:56 +00:00
|
|
|
if ((sigprop(sig) & SIGPROP_CORE) &&
|
|
|
|
thread_single(p, SINGLE_NO_EXIT) == 0) {
|
1999-09-29 15:03:48 +00:00
|
|
|
p->p_sig = sig;
|
1994-09-30 00:38:34 +00:00
|
|
|
/*
|
|
|
|
* Log signals which would cause core dumps
|
1995-05-30 08:16:23 +00:00
|
|
|
* (Log as LOG_INFO to appease those who don't want
|
1994-09-30 00:38:34 +00:00
|
|
|
* these messages.)
|
|
|
|
* XXX : Todo, as well as euid, write out ruid too
|
2004-03-05 22:39:53 +00:00
|
|
|
* Note that coredump() drops proc lock.
|
1994-09-30 00:38:34 +00:00
|
|
|
*/
|
2001-09-12 08:38:13 +00:00
|
|
|
if (coredump(td) == 0)
|
1999-09-29 15:03:48 +00:00
|
|
|
sig |= WCOREFLAG;
|
1998-07-28 22:34:12 +00:00
|
|
|
if (kern_logsigexit)
|
|
|
|
log(LOG_INFO,
|
2018-12-29 14:48:51 +00:00
|
|
|
"pid %d (%s), jid %d, uid %d: exited on "
|
2018-12-29 21:36:02 +00:00
|
|
|
"signal %d%s\n", p->p_pid, p->p_comm,
|
|
|
|
p->p_ucred->cr_prison->pr_id,
|
2019-01-04 21:12:17 +00:00
|
|
|
td->td_ucred->cr_uid,
|
1999-09-29 15:03:48 +00:00
|
|
|
sig &~ WCOREFLAG,
|
|
|
|
sig & WCOREFLAG ? " (core dumped)" : "");
|
2004-03-05 22:39:53 +00:00
|
|
|
} else
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_UNLOCK(p);
|
2015-07-18 09:02:50 +00:00
|
|
|
exit1(td, 0, sig);
|
1994-05-24 10:09:53 +00:00
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
2005-11-08 09:09:26 +00:00
|
|
|
/*
|
2006-02-04 14:10:57 +00:00
|
|
|
* Send queued SIGCHLD to parent when child process's state
|
|
|
|
* is changed.
|
2005-11-08 09:09:26 +00:00
|
|
|
*/
|
2006-02-04 14:10:57 +00:00
|
|
|
static void
|
|
|
|
sigparent(struct proc *p, int reason, int status)
|
2005-11-08 09:09:26 +00:00
|
|
|
{
|
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
|
|
|
PROC_LOCK_ASSERT(p->p_pptr, MA_OWNED);
|
|
|
|
|
|
|
|
if (p->p_ksi != NULL) {
|
|
|
|
p->p_ksi->ksi_signo = SIGCHLD;
|
|
|
|
p->p_ksi->ksi_code = reason;
|
2006-02-04 14:10:57 +00:00
|
|
|
p->p_ksi->ksi_status = status;
|
2005-11-08 09:09:26 +00:00
|
|
|
p->p_ksi->ksi_pid = p->p_pid;
|
|
|
|
p->p_ksi->ksi_uid = p->p_ucred->cr_ruid;
|
|
|
|
if (KSI_ONQ(p->p_ksi))
|
|
|
|
return;
|
|
|
|
}
|
2010-06-29 20:41:52 +00:00
|
|
|
pksignal(p->p_pptr, SIGCHLD, p->p_ksi);
|
2005-11-08 09:09:26 +00:00
|
|
|
}
|
|
|
|
|
2006-02-04 14:10:57 +00:00
|
|
|
static void
|
2013-11-17 22:31:23 +00:00
|
|
|
childproc_jobstate(struct proc *p, int reason, int sig)
|
2005-11-08 09:09:26 +00:00
|
|
|
{
|
2006-02-04 14:10:57 +00:00
|
|
|
struct sigacts *ps;
|
|
|
|
|
2005-11-08 09:09:26 +00:00
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
2006-02-04 14:10:57 +00:00
|
|
|
PROC_LOCK_ASSERT(p->p_pptr, MA_OWNED);
|
2005-11-08 09:09:26 +00:00
|
|
|
|
2006-02-04 14:10:57 +00:00
|
|
|
/*
|
|
|
|
* Wake up parent sleeping in kern_wait(), also send
|
|
|
|
* SIGCHLD to parent, but SIGCHLD does not guarantee
|
|
|
|
* that parent will awake, because parent may masked
|
|
|
|
* the signal.
|
|
|
|
*/
|
|
|
|
p->p_pptr->p_flag |= P_STATCHILD;
|
|
|
|
wakeup(p->p_pptr);
|
|
|
|
|
|
|
|
ps = p->p_pptr->p_sigacts;
|
|
|
|
mtx_lock(&ps->ps_mtx);
|
|
|
|
if ((ps->ps_flag & PS_NOCLDSTOP) == 0) {
|
|
|
|
mtx_unlock(&ps->ps_mtx);
|
2013-11-17 22:31:23 +00:00
|
|
|
sigparent(p, reason, sig);
|
2006-02-04 14:10:57 +00:00
|
|
|
} else
|
|
|
|
mtx_unlock(&ps->ps_mtx);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
childproc_stopped(struct proc *p, int reason)
|
|
|
|
{
|
2015-07-18 09:02:50 +00:00
|
|
|
|
|
|
|
childproc_jobstate(p, reason, p->p_xsig);
|
2006-02-04 14:10:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
childproc_continued(struct proc *p)
|
|
|
|
{
|
|
|
|
childproc_jobstate(p, CLD_CONTINUED, SIGCONT);
|
2005-11-08 09:09:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
childproc_exited(struct proc *p)
|
|
|
|
{
|
2015-07-18 09:02:50 +00:00
|
|
|
int reason, status;
|
2005-11-08 09:09:26 +00:00
|
|
|
|
2015-07-18 09:02:50 +00:00
|
|
|
if (WCOREDUMP(p->p_xsig)) {
|
|
|
|
reason = CLD_DUMPED;
|
|
|
|
status = WTERMSIG(p->p_xsig);
|
|
|
|
} else if (WIFSIGNALED(p->p_xsig)) {
|
|
|
|
reason = CLD_KILLED;
|
|
|
|
status = WTERMSIG(p->p_xsig);
|
|
|
|
} else {
|
|
|
|
reason = CLD_EXITED;
|
|
|
|
status = p->p_xexit;
|
|
|
|
}
|
2006-02-04 14:10:57 +00:00
|
|
|
/*
|
|
|
|
* XXX avoid calling wakeup(p->p_pptr), the work is
|
|
|
|
* done in exit1().
|
|
|
|
*/
|
|
|
|
sigparent(p, reason, status);
|
2005-11-08 09:09:26 +00:00
|
|
|
}
|
|
|
|
|
2018-07-15 17:10:12 +00:00
|
|
|
#define MAX_NUM_CORE_FILES 100000
|
2016-07-27 03:21:02 +00:00
|
|
|
#ifndef NUM_CORE_FILES
|
|
|
|
#define NUM_CORE_FILES 5
|
|
|
|
#endif
|
|
|
|
CTASSERT(NUM_CORE_FILES >= 0 && NUM_CORE_FILES <= MAX_NUM_CORE_FILES);
|
|
|
|
static int num_cores = NUM_CORE_FILES;
|
2010-03-02 06:58:58 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
sysctl_debug_num_cores_check (SYSCTL_HANDLER_ARGS)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
int new_val;
|
2010-06-21 09:51:25 +00:00
|
|
|
|
|
|
|
new_val = num_cores;
|
2010-03-02 06:58:58 +00:00
|
|
|
error = sysctl_handle_int(oidp, &new_val, 0, req);
|
|
|
|
if (error != 0 || req->newptr == NULL)
|
|
|
|
return (error);
|
2016-07-27 03:21:02 +00:00
|
|
|
if (new_val > MAX_NUM_CORE_FILES)
|
|
|
|
new_val = MAX_NUM_CORE_FILES;
|
2010-03-02 06:58:58 +00:00
|
|
|
if (new_val < 0)
|
|
|
|
new_val = 0;
|
|
|
|
num_cores = new_val;
|
|
|
|
return (0);
|
|
|
|
}
|
2020-02-26 14:26:36 +00:00
|
|
|
SYSCTL_PROC(_debug, OID_AUTO, ncores,
|
|
|
|
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 0, sizeof(int),
|
|
|
|
sysctl_debug_num_cores_check, "I",
|
|
|
|
"Maximum number of generated process corefiles while using index format");
|
2010-03-02 06:58:58 +00:00
|
|
|
|
2018-02-13 19:28:02 +00:00
|
|
|
#define GZIP_SUFFIX ".gz"
|
|
|
|
#define ZSTD_SUFFIX ".zst"
|
2010-03-02 06:58:58 +00:00
|
|
|
|
2018-01-08 21:27:41 +00:00
|
|
|
int compress_user_cores = 0;
|
2010-03-02 06:58:58 +00:00
|
|
|
|
2018-01-08 21:27:41 +00:00
|
|
|
static int
|
|
|
|
sysctl_compress_user_cores(SYSCTL_HANDLER_ARGS)
|
|
|
|
{
|
|
|
|
int error, val;
|
|
|
|
|
|
|
|
val = compress_user_cores;
|
|
|
|
error = sysctl_handle_int(oidp, &val, 0, req);
|
|
|
|
if (error != 0 || req->newptr == NULL)
|
|
|
|
return (error);
|
|
|
|
if (val != 0 && !compressor_avail(val))
|
|
|
|
return (EINVAL);
|
|
|
|
compress_user_cores = val;
|
|
|
|
return (error);
|
|
|
|
}
|
2020-02-26 14:26:36 +00:00
|
|
|
SYSCTL_PROC(_kern, OID_AUTO, compress_user_cores,
|
|
|
|
CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0, sizeof(int),
|
|
|
|
sysctl_compress_user_cores, "I",
|
2018-02-13 19:28:02 +00:00
|
|
|
"Enable compression of user corefiles ("
|
|
|
|
__XSTRING(COMPRESS_GZIP) " = gzip, "
|
|
|
|
__XSTRING(COMPRESS_ZSTD) " = zstd)");
|
2018-01-08 21:27:41 +00:00
|
|
|
|
|
|
|
int compress_user_cores_level = 6;
|
|
|
|
SYSCTL_INT(_kern, OID_AUTO, compress_user_cores_level, CTLFLAG_RWTUN,
|
|
|
|
&compress_user_cores_level, 0,
|
|
|
|
"Corefile compression level");
|
2010-03-02 06:58:58 +00:00
|
|
|
|
2015-03-21 04:39:33 +00:00
|
|
|
/*
|
|
|
|
* Protect the access to corefilename[] by allproc_lock.
|
|
|
|
*/
|
|
|
|
#define corefilename_lock allproc_lock
|
|
|
|
|
2004-11-15 20:51:32 +00:00
|
|
|
static char corefilename[MAXPATHLEN] = {"%N.core"};
|
2016-06-09 20:23:30 +00:00
|
|
|
TUNABLE_STR("kern.corefile", corefilename, sizeof(corefilename));
|
2015-03-21 04:39:33 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
sysctl_kern_corefile(SYSCTL_HANDLER_ARGS)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
|
|
|
|
sx_xlock(&corefilename_lock);
|
|
|
|
error = sysctl_handle_string(oidp, corefilename, sizeof(corefilename),
|
|
|
|
req);
|
|
|
|
sx_xunlock(&corefilename_lock);
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
2016-06-09 20:23:30 +00:00
|
|
|
SYSCTL_PROC(_kern, OID_AUTO, corefile, CTLTYPE_STRING | CTLFLAG_RW |
|
2015-03-21 04:39:33 +00:00
|
|
|
CTLFLAG_MPSAFE, 0, 0, sysctl_kern_corefile, "A",
|
|
|
|
"Process corefile name format string");
|
1998-07-08 06:38:39 +00:00
|
|
|
|
2018-07-01 17:28:46 +00:00
|
|
|
static void
|
|
|
|
vnode_close_locked(struct thread *td, struct vnode *vp)
|
|
|
|
{
|
|
|
|
|
2020-01-03 22:29:58 +00:00
|
|
|
VOP_UNLOCK(vp);
|
2018-07-01 17:28:46 +00:00
|
|
|
vn_close(vp, FWRITE, td->td_ucred, td);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the core format has a %I in it, then we need to check
|
|
|
|
* for existing corefiles before defining a name.
|
2018-07-15 17:10:12 +00:00
|
|
|
* To do this we iterate over 0..ncores to find a
|
2018-07-01 17:28:46 +00:00
|
|
|
* non-existing core file name to use. If all core files are
|
|
|
|
* already used we choose the oldest one.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
corefile_open_last(struct thread *td, char *name, int indexpos,
|
2018-07-15 17:10:12 +00:00
|
|
|
int indexlen, int ncores, struct vnode **vpp)
|
2018-07-01 17:28:46 +00:00
|
|
|
{
|
|
|
|
struct vnode *oldvp, *nextvp, *vp;
|
|
|
|
struct vattr vattr;
|
|
|
|
struct nameidata nd;
|
|
|
|
int error, i, flags, oflags, cmode;
|
2018-07-15 17:10:12 +00:00
|
|
|
char ch;
|
2018-07-01 17:28:46 +00:00
|
|
|
struct timespec lasttime;
|
|
|
|
|
|
|
|
nextvp = oldvp = NULL;
|
|
|
|
cmode = S_IRUSR | S_IWUSR;
|
|
|
|
oflags = VN_OPEN_NOAUDIT | VN_OPEN_NAMECACHE |
|
|
|
|
(capmode_coredump ? VN_OPEN_NOCAPCHECK : 0);
|
|
|
|
|
2018-07-15 17:10:12 +00:00
|
|
|
for (i = 0; i < ncores; i++) {
|
2018-07-01 17:28:46 +00:00
|
|
|
flags = O_CREAT | FWRITE | O_NOFOLLOW;
|
2018-07-15 17:10:12 +00:00
|
|
|
|
|
|
|
ch = name[indexpos + indexlen];
|
|
|
|
(void)snprintf(name + indexpos, indexlen + 1, "%.*u", indexlen,
|
|
|
|
i);
|
|
|
|
name[indexpos + indexlen] = ch;
|
2018-07-01 17:28:46 +00:00
|
|
|
|
|
|
|
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td);
|
|
|
|
error = vn_open_cred(&nd, &flags, cmode, oflags, td->td_ucred,
|
|
|
|
NULL);
|
|
|
|
if (error != 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
vp = nd.ni_vp;
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
|
|
|
if ((flags & O_CREAT) == O_CREAT) {
|
|
|
|
nextvp = vp;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = VOP_GETATTR(vp, &vattr, td->td_ucred);
|
|
|
|
if (error != 0) {
|
|
|
|
vnode_close_locked(td, vp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (oldvp == NULL ||
|
|
|
|
lasttime.tv_sec > vattr.va_mtime.tv_sec ||
|
|
|
|
(lasttime.tv_sec == vattr.va_mtime.tv_sec &&
|
|
|
|
lasttime.tv_nsec >= vattr.va_mtime.tv_nsec)) {
|
|
|
|
if (oldvp != NULL)
|
2020-05-29 07:44:02 +00:00
|
|
|
vn_close(oldvp, FWRITE, td->td_ucred, td);
|
2018-07-01 17:28:46 +00:00
|
|
|
oldvp = vp;
|
2020-05-29 07:44:02 +00:00
|
|
|
VOP_UNLOCK(oldvp);
|
2018-07-01 17:28:46 +00:00
|
|
|
lasttime = vattr.va_mtime;
|
|
|
|
} else {
|
|
|
|
vnode_close_locked(td, vp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (oldvp != NULL) {
|
2019-06-23 21:15:31 +00:00
|
|
|
if (nextvp == NULL) {
|
|
|
|
if ((td->td_proc->p_flag & P_SUGID) != 0) {
|
|
|
|
error = EFAULT;
|
2020-05-29 07:44:02 +00:00
|
|
|
vn_close(oldvp, FWRITE, td->td_ucred, td);
|
2019-06-23 21:15:31 +00:00
|
|
|
} else {
|
|
|
|
nextvp = oldvp;
|
2020-05-29 07:44:02 +00:00
|
|
|
error = vn_lock(nextvp, LK_EXCLUSIVE);
|
|
|
|
if (error != 0) {
|
|
|
|
vn_close(nextvp, FWRITE, td->td_ucred,
|
|
|
|
td);
|
|
|
|
nextvp = NULL;
|
|
|
|
}
|
2019-06-23 21:15:31 +00:00
|
|
|
}
|
|
|
|
} else {
|
2020-05-29 07:44:02 +00:00
|
|
|
vn_close(oldvp, FWRITE, td->td_ucred, td);
|
2019-06-23 21:15:31 +00:00
|
|
|
}
|
2018-07-01 17:28:46 +00:00
|
|
|
}
|
|
|
|
if (error != 0) {
|
|
|
|
if (nextvp != NULL)
|
|
|
|
vnode_close_locked(td, oldvp);
|
|
|
|
} else {
|
|
|
|
*vpp = nextvp;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1998-07-08 06:38:39 +00:00
|
|
|
/*
|
2012-12-19 23:59:48 +00:00
|
|
|
* corefile_open(comm, uid, pid, td, compress, vpp, namep)
|
|
|
|
* Expand the name described in corefilename, using name, uid, and pid
|
|
|
|
* and open/create core file.
|
1998-07-08 06:38:39 +00:00
|
|
|
* corefilename is a printf-like string, with three format specifiers:
|
|
|
|
* %N name of process ("name")
|
|
|
|
* %P process id (pid)
|
|
|
|
* %U user id (uid)
|
|
|
|
* For example, "%N.core" is the default; they can be disabled completely
|
|
|
|
* by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P".
|
|
|
|
* This is controlled by the sysctl variable kern.corefile (see above).
|
|
|
|
*/
|
2012-12-19 23:59:48 +00:00
|
|
|
static int
|
|
|
|
corefile_open(const char *comm, uid_t uid, pid_t pid, struct thread *td,
|
2019-07-16 15:51:09 +00:00
|
|
|
int compress, int signum, struct vnode **vpp, char **namep)
|
2002-05-08 09:06:47 +00:00
|
|
|
{
|
2008-03-08 16:31:29 +00:00
|
|
|
struct sbuf sb;
|
2018-07-01 17:28:46 +00:00
|
|
|
struct nameidata nd;
|
2008-03-08 16:31:29 +00:00
|
|
|
const char *format;
|
2012-12-19 23:59:48 +00:00
|
|
|
char *hostname, *name;
|
2018-07-15 17:10:12 +00:00
|
|
|
int cmode, error, flags, i, indexpos, indexlen, oflags, ncores;
|
2012-11-27 10:11:54 +00:00
|
|
|
|
2010-04-30 03:15:00 +00:00
|
|
|
hostname = NULL;
|
2002-05-08 09:06:47 +00:00
|
|
|
format = corefilename;
|
2012-12-19 12:00:09 +00:00
|
|
|
name = malloc(MAXPATHLEN, M_TEMP, M_WAITOK | M_ZERO);
|
2018-07-15 17:10:12 +00:00
|
|
|
indexlen = 0;
|
2010-03-02 06:58:58 +00:00
|
|
|
indexpos = -1;
|
2018-07-15 17:10:12 +00:00
|
|
|
ncores = num_cores;
|
2012-12-17 10:48:10 +00:00
|
|
|
(void)sbuf_new(&sb, name, MAXPATHLEN, SBUF_FIXEDLEN);
|
2015-03-21 04:39:33 +00:00
|
|
|
sx_slock(&corefilename_lock);
|
2012-12-19 12:10:14 +00:00
|
|
|
for (i = 0; format[i] != '\0'; i++) {
|
1998-07-08 06:38:39 +00:00
|
|
|
switch (format[i]) {
|
|
|
|
case '%': /* Format character */
|
|
|
|
i++;
|
|
|
|
switch (format[i]) {
|
|
|
|
case '%':
|
2008-03-08 16:31:29 +00:00
|
|
|
sbuf_putc(&sb, '%');
|
1998-07-08 06:38:39 +00:00
|
|
|
break;
|
2010-03-02 06:58:58 +00:00
|
|
|
case 'H': /* hostname */
|
2010-04-30 03:15:00 +00:00
|
|
|
if (hostname == NULL) {
|
|
|
|
hostname = malloc(MAXHOSTNAMELEN,
|
2012-12-19 12:00:09 +00:00
|
|
|
M_TEMP, M_WAITOK);
|
2012-12-19 12:10:14 +00:00
|
|
|
}
|
2010-03-02 06:58:58 +00:00
|
|
|
getcredhostname(td->td_ucred, hostname,
|
2010-04-30 03:15:00 +00:00
|
|
|
MAXHOSTNAMELEN);
|
2010-03-02 06:58:58 +00:00
|
|
|
sbuf_printf(&sb, "%s", hostname);
|
|
|
|
break;
|
2012-12-19 12:10:14 +00:00
|
|
|
case 'I': /* autoincrementing index */
|
2018-07-15 17:10:12 +00:00
|
|
|
if (indexpos != -1) {
|
|
|
|
sbuf_printf(&sb, "%%I");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
indexpos = sbuf_len(&sb);
|
|
|
|
sbuf_printf(&sb, "%u", ncores - 1);
|
|
|
|
indexlen = sbuf_len(&sb) - indexpos;
|
2010-03-02 06:58:58 +00:00
|
|
|
break;
|
1998-07-08 06:38:39 +00:00
|
|
|
case 'N': /* process name */
|
2012-12-17 10:48:10 +00:00
|
|
|
sbuf_printf(&sb, "%s", comm);
|
1998-07-08 06:38:39 +00:00
|
|
|
break;
|
|
|
|
case 'P': /* process id */
|
2008-03-08 16:31:29 +00:00
|
|
|
sbuf_printf(&sb, "%u", pid);
|
1998-07-08 06:38:39 +00:00
|
|
|
break;
|
2019-07-16 15:51:09 +00:00
|
|
|
case 'S': /* signal number */
|
|
|
|
sbuf_printf(&sb, "%i", signum);
|
|
|
|
break;
|
1998-07-08 06:38:39 +00:00
|
|
|
case 'U': /* user id */
|
2008-03-08 16:31:29 +00:00
|
|
|
sbuf_printf(&sb, "%u", uid);
|
1998-07-08 06:38:39 +00:00
|
|
|
break;
|
|
|
|
default:
|
2012-11-27 10:11:54 +00:00
|
|
|
log(LOG_ERR,
|
2008-03-08 16:31:29 +00:00
|
|
|
"Unknown format character %c in "
|
|
|
|
"corename `%s'\n", format[i], format);
|
2012-12-19 12:10:14 +00:00
|
|
|
break;
|
1998-07-08 06:38:39 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2008-03-08 16:31:29 +00:00
|
|
|
sbuf_putc(&sb, format[i]);
|
2013-02-17 11:47:58 +00:00
|
|
|
break;
|
1998-07-08 06:38:39 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-21 04:39:33 +00:00
|
|
|
sx_sunlock(&corefilename_lock);
|
2010-04-30 03:15:00 +00:00
|
|
|
free(hostname, M_TEMP);
|
2018-01-08 21:27:41 +00:00
|
|
|
if (compress == COMPRESS_GZIP)
|
2018-02-13 19:28:02 +00:00
|
|
|
sbuf_printf(&sb, GZIP_SUFFIX);
|
|
|
|
else if (compress == COMPRESS_ZSTD)
|
|
|
|
sbuf_printf(&sb, ZSTD_SUFFIX);
|
2010-09-10 16:42:16 +00:00
|
|
|
if (sbuf_error(&sb) != 0) {
|
2008-03-08 16:31:29 +00:00
|
|
|
log(LOG_ERR, "pid %ld (%s), uid (%lu): corename is too "
|
2012-12-17 10:48:10 +00:00
|
|
|
"long\n", (long)pid, comm, (u_long)uid);
|
2010-04-30 03:15:00 +00:00
|
|
|
sbuf_delete(&sb);
|
2012-12-17 10:48:10 +00:00
|
|
|
free(name, M_TEMP);
|
2012-12-19 23:59:48 +00:00
|
|
|
return (ENOMEM);
|
2008-03-08 16:31:29 +00:00
|
|
|
}
|
|
|
|
sbuf_finish(&sb);
|
|
|
|
sbuf_delete(&sb);
|
2010-03-02 06:58:58 +00:00
|
|
|
|
|
|
|
if (indexpos != -1) {
|
2018-07-15 17:10:12 +00:00
|
|
|
error = corefile_open_last(td, name, indexpos, indexlen, ncores,
|
|
|
|
vpp);
|
2018-07-01 17:28:46 +00:00
|
|
|
if (error != 0) {
|
|
|
|
log(LOG_ERR,
|
|
|
|
"pid %d (%s), uid (%u): Path `%s' failed "
|
|
|
|
"on initial open test, error = %d\n",
|
|
|
|
pid, comm, uid, name, error);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cmode = S_IRUSR | S_IWUSR;
|
|
|
|
oflags = VN_OPEN_NOAUDIT | VN_OPEN_NAMECACHE |
|
|
|
|
(capmode_coredump ? VN_OPEN_NOCAPCHECK : 0);
|
|
|
|
flags = O_CREAT | FWRITE | O_NOFOLLOW;
|
2019-06-23 21:15:31 +00:00
|
|
|
if ((td->td_proc->p_flag & P_SUGID) != 0)
|
|
|
|
flags |= O_EXCL;
|
2018-07-01 17:28:46 +00:00
|
|
|
|
|
|
|
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td);
|
|
|
|
error = vn_open_cred(&nd, &flags, cmode, oflags, td->td_ucred,
|
|
|
|
NULL);
|
|
|
|
if (error == 0) {
|
|
|
|
*vpp = nd.ni_vp;
|
|
|
|
NDFREE(&nd, NDF_ONLY_PNBUF);
|
2010-03-02 06:58:58 +00:00
|
|
|
}
|
|
|
|
}
|
2012-12-19 23:59:48 +00:00
|
|
|
|
2018-07-01 17:28:46 +00:00
|
|
|
if (error != 0) {
|
2012-12-19 23:59:48 +00:00
|
|
|
#ifdef AUDIT
|
|
|
|
audit_proc_coredump(td, name, error);
|
|
|
|
#endif
|
|
|
|
free(name, M_TEMP);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
*namep = name;
|
|
|
|
return (0);
|
1998-07-08 06:38:39 +00:00
|
|
|
}
|
|
|
|
|
1999-09-01 00:29:56 +00:00
|
|
|
/*
|
|
|
|
* Dump a process' core. The main routine does some
|
|
|
|
* policy checking, and creates the name of the coredump;
|
|
|
|
* then it passes on a vnode and a size limit to the process-specific
|
|
|
|
* coredump routine if there is one; if there _is not_ one, it returns
|
|
|
|
* ENOSYS; otherwise it returns the error from the process-specific routine.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int
|
2001-09-12 08:38:13 +00:00
|
|
|
coredump(struct thread *td)
|
1999-09-01 00:29:56 +00:00
|
|
|
{
|
2001-09-12 08:38:13 +00:00
|
|
|
struct proc *p = td->td_proc;
|
2012-12-17 10:51:22 +00:00
|
|
|
struct ucred *cred = td->td_ucred;
|
|
|
|
struct vnode *vp;
|
2001-09-08 20:02:33 +00:00
|
|
|
struct flock lf;
|
1999-09-01 00:29:56 +00:00
|
|
|
struct vattr vattr;
|
2020-02-01 20:38:38 +00:00
|
|
|
size_t fullpathsize;
|
2012-12-19 23:59:48 +00:00
|
|
|
int error, error1, locked;
|
1999-09-01 00:29:56 +00:00
|
|
|
char *name; /* name of corefile */
|
2014-10-04 18:35:00 +00:00
|
|
|
void *rl_cookie;
|
1999-09-01 00:29:56 +00:00
|
|
|
off_t limit;
|
2015-02-09 23:13:50 +00:00
|
|
|
char *fullpath, *freepath = NULL;
|
2018-06-27 04:11:09 +00:00
|
|
|
struct sbuf *sb;
|
1999-09-01 00:29:56 +00:00
|
|
|
|
2004-03-05 22:39:53 +00:00
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
2005-04-10 02:31:24 +00:00
|
|
|
MPASS((p->p_flag & P_HADTHREADS) == 0 || p->p_singlethread == td);
|
2001-03-07 02:59:54 +00:00
|
|
|
|
2015-01-18 15:13:11 +00:00
|
|
|
if (!do_coredump || (!sugid_coredump && (p->p_flag & P_SUGID) != 0) ||
|
|
|
|
(p->p_flag2 & P2_NOTRACE) != 0) {
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_UNLOCK(p);
|
1999-09-01 00:29:56 +00:00
|
|
|
return (EFAULT);
|
2001-03-07 02:59:54 +00:00
|
|
|
}
|
2012-11-27 10:11:54 +00:00
|
|
|
|
1999-09-01 00:29:56 +00:00
|
|
|
/*
|
1999-10-30 18:55:11 +00:00
|
|
|
* Note that the bulk of limit checking is done after
|
|
|
|
* the corefile is created. The exception is if the limit
|
|
|
|
* for corefiles is 0, in which case we don't bother
|
|
|
|
* creating the corefile at all. This layout means that
|
|
|
|
* a corefile is truncated instead of not being created,
|
|
|
|
* if it is larger than the limit.
|
1999-09-01 00:29:56 +00:00
|
|
|
*/
|
2015-06-10 10:48:12 +00:00
|
|
|
limit = (off_t)lim_cur(td, RLIMIT_CORE);
|
2011-05-26 18:54:07 +00:00
|
|
|
if (limit == 0 || racct_get_available(p, RACCT_CORE) == 0) {
|
|
|
|
PROC_UNLOCK(p);
|
2004-02-04 21:52:57 +00:00
|
|
|
return (EFBIG);
|
Implement AUE_CORE, which adds process core dump support into the kernel.
This change introduces audit_proc_coredump() which is called by coredump(9)
to create an audit record for the coredump event. When a process
dumps a core, it could be security relevant. It could be an indicator that
a stack within the process has been overflowed with an incorrectly constructed
malicious payload or a number of other events.
The record that is generated looks like this:
header,111,10,process dumped core,0,Thu Oct 25 19:36:29 2007, + 179 msec
argument,0,0xb,signal
path,/usr/home/csjp/test.core
subject,csjp,csjp,staff,csjp,staff,1101,1095,50457,10.37.129.2
return,success,1
trailer,111
- We allocate a completely new record to make sure we arent clobbering
the audit data associated with the syscall that produced the core
(assuming the core is being generated in response to SIGABRT and not
an invalid memory access).
- Shuffle around expand_name() so we can use the coredump name at the very
beginning of the coredump call. Make sure we free the storage referenced
by "name" if we need to bail out early.
- Audit both successful and failed coredump creation efforts
Obtained from: TrustedBSD Project
Reviewed by: rwatson
MFC after: 1 month
2007-10-26 01:23:07 +00:00
|
|
|
}
|
2011-05-26 18:54:07 +00:00
|
|
|
PROC_UNLOCK(p);
|
1999-10-30 18:55:11 +00:00
|
|
|
|
2015-03-09 03:50:53 +00:00
|
|
|
error = corefile_open(p->p_comm, cred->cr_uid, p->p_pid, td,
|
2019-07-16 15:51:09 +00:00
|
|
|
compress_user_cores, p->p_sig, &vp, &name);
|
2012-12-19 23:59:48 +00:00
|
|
|
if (error != 0)
|
1999-09-01 00:29:56 +00:00
|
|
|
return (error);
|
2001-09-08 20:02:33 +00:00
|
|
|
|
2014-10-04 18:35:00 +00:00
|
|
|
/*
|
|
|
|
* Don't dump to non-regular files or files with links.
|
2019-06-23 21:15:31 +00:00
|
|
|
* Do not dump into system files. Effective user must own the corefile.
|
2014-10-04 18:35:00 +00:00
|
|
|
*/
|
2012-12-17 10:51:22 +00:00
|
|
|
if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred) != 0 ||
|
2019-06-23 18:35:11 +00:00
|
|
|
vattr.va_nlink != 1 || (vp->v_vflag & VV_SYSTEM) != 0 ||
|
2019-06-23 21:15:31 +00:00
|
|
|
vattr.va_uid != cred->cr_uid) {
|
2020-01-03 22:29:58 +00:00
|
|
|
VOP_UNLOCK(vp);
|
2002-07-10 06:31:35 +00:00
|
|
|
error = EFAULT;
|
2015-02-24 13:07:31 +00:00
|
|
|
goto out;
|
2002-07-10 06:31:35 +00:00
|
|
|
}
|
|
|
|
|
2020-01-03 22:29:58 +00:00
|
|
|
VOP_UNLOCK(vp);
|
2014-10-04 18:35:00 +00:00
|
|
|
|
|
|
|
/* Postpone other writers, including core dumps of other processes. */
|
|
|
|
rl_cookie = vn_rangelock_wlock(vp, 0, OFF_MAX);
|
|
|
|
|
2001-09-08 20:02:33 +00:00
|
|
|
lf.l_whence = SEEK_SET;
|
|
|
|
lf.l_start = 0;
|
|
|
|
lf.l_len = 0;
|
|
|
|
lf.l_type = F_WRLCK;
|
2003-10-25 16:14:09 +00:00
|
|
|
locked = (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &lf, F_FLOCK) == 0);
|
2001-09-08 20:02:33 +00:00
|
|
|
|
1999-09-01 00:29:56 +00:00
|
|
|
VATTR_NULL(&vattr);
|
|
|
|
vattr.va_size = 0;
|
2004-08-09 05:46:46 +00:00
|
|
|
if (set_core_nodump_flag)
|
|
|
|
vattr.va_flags = UF_NODUMP;
|
2008-01-10 01:10:58 +00:00
|
|
|
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
2008-08-28 15:23:18 +00:00
|
|
|
VOP_SETATTR(vp, &vattr, cred);
|
2020-01-03 22:29:58 +00:00
|
|
|
VOP_UNLOCK(vp);
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_LOCK(p);
|
1999-09-01 00:29:56 +00:00
|
|
|
p->p_acflag |= ACORE;
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_UNLOCK(p);
|
1999-09-01 00:29:56 +00:00
|
|
|
|
2012-11-27 10:11:54 +00:00
|
|
|
if (p->p_sysent->sv_coredump != NULL) {
|
2018-01-08 21:27:41 +00:00
|
|
|
error = p->p_sysent->sv_coredump(td, vp, limit, 0);
|
2012-11-27 10:11:54 +00:00
|
|
|
} else {
|
|
|
|
error = ENOSYS;
|
|
|
|
}
|
1999-09-01 00:29:56 +00:00
|
|
|
|
2003-10-25 16:14:09 +00:00
|
|
|
if (locked) {
|
|
|
|
lf.l_type = F_UNLCK;
|
|
|
|
VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_FLOCK);
|
|
|
|
}
|
2014-10-04 18:35:00 +00:00
|
|
|
vn_rangelock_unlock(vp, rl_cookie);
|
2015-02-24 13:07:31 +00:00
|
|
|
|
2015-02-09 23:13:50 +00:00
|
|
|
/*
|
|
|
|
* Notify the userland helper that a process triggered a core dump.
|
|
|
|
* This allows the helper to run an automated debugging session.
|
|
|
|
*/
|
2015-02-24 13:07:31 +00:00
|
|
|
if (error != 0 || coredump_devctl == 0)
|
2015-02-09 23:13:50 +00:00
|
|
|
goto out;
|
2018-06-27 04:11:09 +00:00
|
|
|
sb = sbuf_new_auto();
|
2020-08-24 08:57:02 +00:00
|
|
|
if (vn_fullpath_global(p->p_textvp, &fullpath, &freepath) != 0)
|
2018-06-27 04:11:09 +00:00
|
|
|
goto out2;
|
|
|
|
sbuf_printf(sb, "comm=\"");
|
|
|
|
devctl_safe_quote_sb(sb, fullpath);
|
2015-02-10 04:34:39 +00:00
|
|
|
free(freepath, M_TEMP);
|
2018-06-27 04:11:09 +00:00
|
|
|
sbuf_printf(sb, "\" core=\"");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We can't lookup core file vp directly. When we're replacing a core, and
|
|
|
|
* other random times, we flush the name cache, so it will fail. Instead,
|
|
|
|
* if the path of the core is relative, add the current dir in front if it.
|
|
|
|
*/
|
|
|
|
if (name[0] != '/') {
|
2020-02-01 20:38:38 +00:00
|
|
|
fullpathsize = MAXPATHLEN;
|
|
|
|
freepath = malloc(fullpathsize, M_TEMP, M_WAITOK);
|
2020-08-24 08:57:02 +00:00
|
|
|
if (vn_getcwd(freepath, &fullpath, &fullpathsize) != 0) {
|
2020-02-01 20:38:38 +00:00
|
|
|
free(freepath, M_TEMP);
|
2018-06-27 04:11:09 +00:00
|
|
|
goto out2;
|
|
|
|
}
|
|
|
|
devctl_safe_quote_sb(sb, fullpath);
|
2020-02-01 20:38:38 +00:00
|
|
|
free(freepath, M_TEMP);
|
2018-06-27 04:11:09 +00:00
|
|
|
sbuf_putc(sb, '/');
|
|
|
|
}
|
|
|
|
devctl_safe_quote_sb(sb, name);
|
|
|
|
sbuf_printf(sb, "\"");
|
|
|
|
if (sbuf_finish(sb) == 0)
|
|
|
|
devctl_notify("kernel", "signal", "coredump", sbuf_data(sb));
|
|
|
|
out2:
|
|
|
|
sbuf_delete(sb);
|
2015-02-09 23:13:50 +00:00
|
|
|
out:
|
2015-02-24 13:07:31 +00:00
|
|
|
error1 = vn_close(vp, FWRITE, cred, td);
|
|
|
|
if (error == 0)
|
|
|
|
error = error1;
|
Implement AUE_CORE, which adds process core dump support into the kernel.
This change introduces audit_proc_coredump() which is called by coredump(9)
to create an audit record for the coredump event. When a process
dumps a core, it could be security relevant. It could be an indicator that
a stack within the process has been overflowed with an incorrectly constructed
malicious payload or a number of other events.
The record that is generated looks like this:
header,111,10,process dumped core,0,Thu Oct 25 19:36:29 2007, + 179 msec
argument,0,0xb,signal
path,/usr/home/csjp/test.core
subject,csjp,csjp,staff,csjp,staff,1101,1095,50457,10.37.129.2
return,success,1
trailer,111
- We allocate a completely new record to make sure we arent clobbering
the audit data associated with the syscall that produced the core
(assuming the core is being generated in response to SIGABRT and not
an invalid memory access).
- Shuffle around expand_name() so we can use the coredump name at the very
beginning of the coredump call. Make sure we free the storage referenced
by "name" if we need to bail out early.
- Audit both successful and failed coredump creation efforts
Obtained from: TrustedBSD Project
Reviewed by: rwatson
MFC after: 1 month
2007-10-26 01:23:07 +00:00
|
|
|
#ifdef AUDIT
|
|
|
|
audit_proc_coredump(td, name, error);
|
|
|
|
#endif
|
|
|
|
free(name, M_TEMP);
|
1999-09-01 00:29:56 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1994-05-24 10:09:53 +00:00
|
|
|
/*
|
2007-03-04 22:36:48 +00:00
|
|
|
* Nonexistent system call-- signal process (may want to handle it). Flag
|
|
|
|
* error in case process won't see signal immediately (blocked or ignored).
|
1994-05-24 10:09:53 +00:00
|
|
|
*/
|
1995-11-12 06:43:28 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
1994-05-24 10:09:53 +00:00
|
|
|
struct nosys_args {
|
|
|
|
int dummy;
|
|
|
|
};
|
1995-11-12 06:43:28 +00:00
|
|
|
#endif
|
1994-05-24 10:09:53 +00:00
|
|
|
/* ARGSUSED */
|
1994-05-25 09:21:21 +00:00
|
|
|
int
|
2017-03-02 22:17:53 +00:00
|
|
|
nosys(struct thread *td, struct nosys_args *args)
|
1994-05-24 10:09:53 +00:00
|
|
|
{
|
2017-06-12 21:11:11 +00:00
|
|
|
struct proc *p;
|
|
|
|
|
|
|
|
p = td->td_proc;
|
2001-09-12 08:38:13 +00:00
|
|
|
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_LOCK(p);
|
2012-08-18 18:17:10 +00:00
|
|
|
tdsignal(td, SIGSYS);
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_UNLOCK(p);
|
2017-07-27 20:45:41 +00:00
|
|
|
if (kern_lognosys == 1 || kern_lognosys == 3) {
|
2017-06-12 21:11:11 +00:00
|
|
|
uprintf("pid %d comm %s: nosys %d\n", p->p_pid, p->p_comm,
|
|
|
|
td->td_sa.code);
|
2017-07-27 20:45:41 +00:00
|
|
|
}
|
2020-09-02 23:17:33 +00:00
|
|
|
if (kern_lognosys == 2 || kern_lognosys == 3 ||
|
|
|
|
(p->p_pid == 1 && (kern_lognosys & 3) == 0)) {
|
2017-07-27 20:45:41 +00:00
|
|
|
printf("pid %d comm %s: nosys %d\n", p->p_pid, p->p_comm,
|
|
|
|
td->td_sa.code);
|
|
|
|
}
|
2002-05-05 04:50:47 +00:00
|
|
|
return (ENOSYS);
|
1994-05-24 10:09:53 +00:00
|
|
|
}
|
Installed the second patch attached to kern/7899 with some changes suggested
by bde, a few other tweaks to get the patch to apply cleanly again and
some improvements to the comments.
This change closes some fairly minor security holes associated with
F_SETOWN, fixes a few bugs, and removes some limitations that F_SETOWN
had on tty devices. For more details, see the description on the PR.
Because this patch increases the size of the proc and pgrp structures,
it is necessary to re-install the includes and recompile libkvm,
the vinum lkm, fstat, gcore, gdb, ipfilter, ps, top, and w.
PR: kern/7899
Reviewed by: bde, elvind
1998-11-11 10:04:13 +00:00
|
|
|
|
|
|
|
/*
|
2007-03-04 22:36:48 +00:00
|
|
|
* Send a SIGIO or SIGURG signal to a process or process group using stored
|
|
|
|
* credentials rather than those of the current process.
|
Installed the second patch attached to kern/7899 with some changes suggested
by bde, a few other tweaks to get the patch to apply cleanly again and
some improvements to the comments.
This change closes some fairly minor security holes associated with
F_SETOWN, fixes a few bugs, and removes some limitations that F_SETOWN
had on tty devices. For more details, see the description on the PR.
Because this patch increases the size of the proc and pgrp structures,
it is necessary to re-install the includes and recompile libkvm,
the vinum lkm, fstat, gcore, gdb, ipfilter, ps, top, and w.
PR: kern/7899
Reviewed by: bde, elvind
1998-11-11 10:04:13 +00:00
|
|
|
*/
|
|
|
|
void
|
2017-03-02 22:17:53 +00:00
|
|
|
pgsigio(struct sigio **sigiop, int sig, int checkctty)
|
Installed the second patch attached to kern/7899 with some changes suggested
by bde, a few other tweaks to get the patch to apply cleanly again and
some improvements to the comments.
This change closes some fairly minor security holes associated with
F_SETOWN, fixes a few bugs, and removes some limitations that F_SETOWN
had on tty devices. For more details, see the description on the PR.
Because this patch increases the size of the proc and pgrp structures,
it is necessary to re-install the includes and recompile libkvm,
the vinum lkm, fstat, gcore, gdb, ipfilter, ps, top, and w.
PR: kern/7899
Reviewed by: bde, elvind
1998-11-11 10:04:13 +00:00
|
|
|
{
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
ksiginfo_t ksi;
|
2002-05-01 20:44:46 +00:00
|
|
|
struct sigio *sigio;
|
2002-02-23 11:12:57 +00:00
|
|
|
|
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag
that allows sigqueue_add() to fail while trying to allocate memory for
new siginfo. When the flag is not set, behaviour is the same as for
KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is
kept to preserve KBI.
Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is
generated by kernel. Deliver siginfo when signal is generated by kill(2)
family of syscalls (SI_USER with properly filled si_uid and si_pid), or
by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag
is not set for the ksi, low memory condition cause old behaviour.
Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL
si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add
pksignal(9) that behaves like psignal but takes ksi, and ddb kill
command implemented as pksignal(..., ksi = NULL) to not do allocation
while in debugger.
While there, remove some register specifiers and use ANSI C prototypes.
Reviewed by: davidxu
MFC after: 1 month
2009-11-17 11:39:15 +00:00
|
|
|
ksiginfo_init(&ksi);
|
|
|
|
ksi.ksi_signo = sig;
|
|
|
|
ksi.ksi_code = SI_KERNEL;
|
|
|
|
|
2002-05-01 20:44:46 +00:00
|
|
|
SIGIO_LOCK();
|
|
|
|
sigio = *sigiop;
|
|
|
|
if (sigio == NULL) {
|
|
|
|
SIGIO_UNLOCK();
|
|
|
|
return;
|
|
|
|
}
|
Installed the second patch attached to kern/7899 with some changes suggested
by bde, a few other tweaks to get the patch to apply cleanly again and
some improvements to the comments.
This change closes some fairly minor security holes associated with
F_SETOWN, fixes a few bugs, and removes some limitations that F_SETOWN
had on tty devices. For more details, see the description on the PR.
Because this patch increases the size of the proc and pgrp structures,
it is necessary to re-install the includes and recompile libkvm,
the vinum lkm, fstat, gcore, gdb, ipfilter, ps, top, and w.
PR: kern/7899
Reviewed by: bde, elvind
1998-11-11 10:04:13 +00:00
|
|
|
if (sigio->sio_pgid > 0) {
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_LOCK(sigio->sio_proc);
|
2002-01-10 01:25:35 +00:00
|
|
|
if (CANSIGIO(sigio->sio_ucred, sigio->sio_proc->p_ucred))
|
2011-09-16 13:58:51 +00:00
|
|
|
kern_psignal(sigio->sio_proc, sig);
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_UNLOCK(sigio->sio_proc);
|
Installed the second patch attached to kern/7899 with some changes suggested
by bde, a few other tweaks to get the patch to apply cleanly again and
some improvements to the comments.
This change closes some fairly minor security holes associated with
F_SETOWN, fixes a few bugs, and removes some limitations that F_SETOWN
had on tty devices. For more details, see the description on the PR.
Because this patch increases the size of the proc and pgrp structures,
it is necessary to re-install the includes and recompile libkvm,
the vinum lkm, fstat, gcore, gdb, ipfilter, ps, top, and w.
PR: kern/7899
Reviewed by: bde, elvind
1998-11-11 10:04:13 +00:00
|
|
|
} else if (sigio->sio_pgid < 0) {
|
|
|
|
struct proc *p;
|
|
|
|
|
2002-02-23 11:12:57 +00:00
|
|
|
PGRP_LOCK(sigio->sio_pgrp);
|
2001-03-07 02:59:54 +00:00
|
|
|
LIST_FOREACH(p, &sigio->sio_pgrp->pg_members, p_pglist) {
|
|
|
|
PROC_LOCK(p);
|
2011-04-06 17:47:22 +00:00
|
|
|
if (p->p_state == PRS_NORMAL &&
|
|
|
|
CANSIGIO(sigio->sio_ucred, p->p_ucred) &&
|
Installed the second patch attached to kern/7899 with some changes suggested
by bde, a few other tweaks to get the patch to apply cleanly again and
some improvements to the comments.
This change closes some fairly minor security holes associated with
F_SETOWN, fixes a few bugs, and removes some limitations that F_SETOWN
had on tty devices. For more details, see the description on the PR.
Because this patch increases the size of the proc and pgrp structures,
it is necessary to re-install the includes and recompile libkvm,
the vinum lkm, fstat, gcore, gdb, ipfilter, ps, top, and w.
PR: kern/7899
Reviewed by: bde, elvind
1998-11-11 10:04:13 +00:00
|
|
|
(checkctty == 0 || (p->p_flag & P_CONTROLT)))
|
2011-09-16 13:58:51 +00:00
|
|
|
kern_psignal(p, sig);
|
2001-03-07 02:59:54 +00:00
|
|
|
PROC_UNLOCK(p);
|
|
|
|
}
|
2002-02-23 11:12:57 +00:00
|
|
|
PGRP_UNLOCK(sigio->sio_pgrp);
|
Installed the second patch attached to kern/7899 with some changes suggested
by bde, a few other tweaks to get the patch to apply cleanly again and
some improvements to the comments.
This change closes some fairly minor security holes associated with
F_SETOWN, fixes a few bugs, and removes some limitations that F_SETOWN
had on tty devices. For more details, see the description on the PR.
Because this patch increases the size of the proc and pgrp structures,
it is necessary to re-install the includes and recompile libkvm,
the vinum lkm, fstat, gcore, gdb, ipfilter, ps, top, and w.
PR: kern/7899
Reviewed by: bde, elvind
1998-11-11 10:04:13 +00:00
|
|
|
}
|
2002-05-01 20:44:46 +00:00
|
|
|
SIGIO_UNLOCK();
|
Installed the second patch attached to kern/7899 with some changes suggested
by bde, a few other tweaks to get the patch to apply cleanly again and
some improvements to the comments.
This change closes some fairly minor security holes associated with
F_SETOWN, fixes a few bugs, and removes some limitations that F_SETOWN
had on tty devices. For more details, see the description on the PR.
Because this patch increases the size of the proc and pgrp structures,
it is necessary to re-install the includes and recompile libkvm,
the vinum lkm, fstat, gcore, gdb, ipfilter, ps, top, and w.
PR: kern/7899
Reviewed by: bde, elvind
1998-11-11 10:04:13 +00:00
|
|
|
}
|
2000-04-16 18:53:38 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
filt_sigattach(struct knote *kn)
|
|
|
|
{
|
|
|
|
struct proc *p = curproc;
|
|
|
|
|
|
|
|
kn->kn_ptr.p_proc = p;
|
|
|
|
kn->kn_flags |= EV_CLEAR; /* automatically set */
|
|
|
|
|
When filt_proc() removes event from the knlist due to the process
exiting (NOTE_EXIT->knlist_remove_inevent()), two things happen:
- knote kn_knlist pointer is reset
- INFLUX knote is removed from the process knlist.
And, there are two consequences:
- KN_LIST_UNLOCK() on such knote is nop
- there is nothing which would block exit1() from processing past the
knlist_destroy() (and knlist_destroy() resets knlist lock pointers).
Both consequences result either in leaked process lock, or
dereferencing NULL function pointers for locking.
Handle this by stopping embedding the process knlist into struct proc.
Instead, the knlist is allocated together with struct proc, but marked
as autodestroy on the zombie reap, by knlist_detach() function. The
knlist is freed when last kevent is removed from the list, in
particular, at the zombie reap time if the list is empty. As result,
the knlist_remove_inevent() is no longer needed and removed.
Other changes:
In filt_procattach(), clear NOTE_EXEC and NOTE_FORK desired events
from kn_sfflags for knote registered by kernel to only get NOTE_CHILD
notifications. The flags leak resulted in excessive
NOTE_EXEC/NOTE_FORK reports.
Fix immediate note activation in filt_procattach(). Condition should
be either the immediate CHILD_NOTE activation, or immediate NOTE_EXIT
report for the exiting process.
In knote_fork(), do not perform racy check for KN_INFLUX before kq
lock is taken. Besides being racy, it did not accounted for notes
just added by scan (KN_SCAN).
Some minor and incomplete style fixes.
Analyzed and tested by: Eric Badger <eric@badgerio.us>
Reviewed by: jhb
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Approved by: re (gjb)
Differential revision: https://reviews.freebsd.org/D6859
2016-06-27 21:52:17 +00:00
|
|
|
knlist_add(p->p_klist, kn, 0);
|
2000-04-16 18:53:38 +00:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
filt_sigdetach(struct knote *kn)
|
|
|
|
{
|
|
|
|
struct proc *p = kn->kn_ptr.p_proc;
|
|
|
|
|
When filt_proc() removes event from the knlist due to the process
exiting (NOTE_EXIT->knlist_remove_inevent()), two things happen:
- knote kn_knlist pointer is reset
- INFLUX knote is removed from the process knlist.
And, there are two consequences:
- KN_LIST_UNLOCK() on such knote is nop
- there is nothing which would block exit1() from processing past the
knlist_destroy() (and knlist_destroy() resets knlist lock pointers).
Both consequences result either in leaked process lock, or
dereferencing NULL function pointers for locking.
Handle this by stopping embedding the process knlist into struct proc.
Instead, the knlist is allocated together with struct proc, but marked
as autodestroy on the zombie reap, by knlist_detach() function. The
knlist is freed when last kevent is removed from the list, in
particular, at the zombie reap time if the list is empty. As result,
the knlist_remove_inevent() is no longer needed and removed.
Other changes:
In filt_procattach(), clear NOTE_EXEC and NOTE_FORK desired events
from kn_sfflags for knote registered by kernel to only get NOTE_CHILD
notifications. The flags leak resulted in excessive
NOTE_EXEC/NOTE_FORK reports.
Fix immediate note activation in filt_procattach(). Condition should
be either the immediate CHILD_NOTE activation, or immediate NOTE_EXIT
report for the exiting process.
In knote_fork(), do not perform racy check for KN_INFLUX before kq
lock is taken. Besides being racy, it did not accounted for notes
just added by scan (KN_SCAN).
Some minor and incomplete style fixes.
Analyzed and tested by: Eric Badger <eric@badgerio.us>
Reviewed by: jhb
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Approved by: re (gjb)
Differential revision: https://reviews.freebsd.org/D6859
2016-06-27 21:52:17 +00:00
|
|
|
knlist_remove(p->p_klist, kn, 0);
|
2000-04-16 18:53:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2012-11-27 10:11:54 +00:00
|
|
|
* signal knotes are shared with proc knotes, so we apply a mask to
|
2000-04-16 18:53:38 +00:00
|
|
|
* the hint in order to differentiate them from process hints. This
|
|
|
|
* could be avoided by using a signal-specific knote list, but probably
|
|
|
|
* isn't worth the trouble.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
filt_signal(struct knote *kn, long hint)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (hint & NOTE_SIGNAL) {
|
|
|
|
hint &= ~NOTE_SIGNAL;
|
|
|
|
|
|
|
|
if (kn->kn_id == hint)
|
|
|
|
kn->kn_data++;
|
|
|
|
}
|
|
|
|
return (kn->kn_data != 0);
|
|
|
|
}
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
|
|
|
|
struct sigacts *
|
|
|
|
sigacts_alloc(void)
|
|
|
|
{
|
|
|
|
struct sigacts *ps;
|
|
|
|
|
|
|
|
ps = malloc(sizeof(struct sigacts), M_SUBPROC, M_WAITOK | M_ZERO);
|
2014-08-24 09:24:37 +00:00
|
|
|
refcount_init(&ps->ps_refcnt, 1);
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
mtx_init(&ps->ps_mtx, "sigacts", NULL, MTX_DEF);
|
|
|
|
return (ps);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
sigacts_free(struct sigacts *ps)
|
|
|
|
{
|
|
|
|
|
2014-07-14 21:12:59 +00:00
|
|
|
if (refcount_release(&ps->ps_refcnt) == 0)
|
|
|
|
return;
|
|
|
|
mtx_destroy(&ps->ps_mtx);
|
|
|
|
free(ps, M_SUBPROC);
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct sigacts *
|
|
|
|
sigacts_hold(struct sigacts *ps)
|
|
|
|
{
|
2014-07-14 21:12:59 +00:00
|
|
|
|
|
|
|
refcount_acquire(&ps->ps_refcnt);
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
return (ps);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
sigacts_copy(struct sigacts *dest, struct sigacts *src)
|
|
|
|
{
|
|
|
|
|
|
|
|
KASSERT(dest->ps_refcnt == 1, ("sigacts_copy to shared dest"));
|
|
|
|
mtx_lock(&src->ps_mtx);
|
|
|
|
bcopy(src, dest, offsetof(struct sigacts, ps_refcnt));
|
|
|
|
mtx_unlock(&src->ps_mtx);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
sigacts_shared(struct sigacts *ps)
|
|
|
|
{
|
|
|
|
|
2014-07-01 06:29:15 +00:00
|
|
|
return (ps->ps_refcnt > 1);
|
- Merge struct procsig with struct sigacts.
- Move struct sigacts out of the u-area and malloc() it using the
M_SUBPROC malloc bucket.
- Add a small sigacts_*() API for managing sigacts structures: sigacts_alloc(),
sigacts_free(), sigacts_copy(), sigacts_share(), and sigacts_shared().
- Remove the p_sigignore, p_sigacts, and p_sigcatch macros.
- Add a mutex to struct sigacts that protects all the members of the struct.
- Add sigacts locking.
- Remove Giant from nosys(), kill(), killpg(), and kern_sigaction() now
that sigacts is locked.
- Several in-kernel functions such as psignal(), tdsignal(), trapsignal(),
and thread_stopped() are now MP safe.
Reviewed by: arch@
Approved by: re (rwatson)
2003-05-13 20:36:02 +00:00
|
|
|
}
|
2019-09-25 19:20:41 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
sig_drop_caught(struct proc *p)
|
|
|
|
{
|
|
|
|
int sig;
|
|
|
|
struct sigacts *ps;
|
|
|
|
|
|
|
|
ps = p->p_sigacts;
|
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
|
|
|
mtx_assert(&ps->ps_mtx, MA_OWNED);
|
|
|
|
while (SIGNOTEMPTY(ps->ps_sigcatch)) {
|
|
|
|
sig = sig_ffs(&ps->ps_sigcatch);
|
|
|
|
sigdflt(ps, sig);
|
|
|
|
if ((sigprop(sig) & SIGPROP_IGNORE) != 0)
|
|
|
|
sigqueue_delete_proc(p, sig);
|
|
|
|
}
|
|
|
|
}
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
|
2020-02-20 15:34:02 +00:00
|
|
|
static void
|
|
|
|
sigfastblock_failed(struct thread *td, bool sendsig, bool write)
|
|
|
|
{
|
|
|
|
ksiginfo_t ksi;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prevent further fetches and SIGSEGVs, allowing thread to
|
|
|
|
* issue syscalls despite corruption.
|
|
|
|
*/
|
|
|
|
sigfastblock_clear(td);
|
|
|
|
|
|
|
|
if (!sendsig)
|
|
|
|
return;
|
|
|
|
ksiginfo_init_trap(&ksi);
|
|
|
|
ksi.ksi_signo = SIGSEGV;
|
|
|
|
ksi.ksi_code = write ? SEGV_ACCERR : SEGV_MAPERR;
|
|
|
|
ksi.ksi_addr = td->td_sigblock_ptr;
|
|
|
|
trapsignal(td, &ksi);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
sigfastblock_fetch_sig(struct thread *td, bool sendsig, uint32_t *valp)
|
|
|
|
{
|
|
|
|
uint32_t res;
|
|
|
|
|
|
|
|
if ((td->td_pflags & TDP_SIGFASTBLOCK) == 0)
|
|
|
|
return (true);
|
|
|
|
if (fueword32((void *)td->td_sigblock_ptr, &res) == -1) {
|
|
|
|
sigfastblock_failed(td, sendsig, false);
|
|
|
|
return (false);
|
|
|
|
}
|
|
|
|
*valp = res;
|
|
|
|
td->td_sigblock_val = res & ~SIGFASTBLOCK_FLAGS;
|
|
|
|
return (true);
|
|
|
|
}
|
|
|
|
|
2020-05-11 22:38:32 +00:00
|
|
|
static void
|
|
|
|
sigfastblock_resched(struct thread *td, bool resched)
|
|
|
|
{
|
|
|
|
struct proc *p;
|
|
|
|
|
|
|
|
if (resched) {
|
|
|
|
p = td->td_proc;
|
|
|
|
PROC_LOCK(p);
|
|
|
|
reschedule_signals(p, td->td_sigmask, 0);
|
|
|
|
PROC_UNLOCK(p);
|
|
|
|
}
|
|
|
|
thread_lock(td);
|
|
|
|
td->td_flags |= TDF_ASTPENDING | TDF_NEEDSIGCHK;
|
|
|
|
thread_unlock(td);
|
|
|
|
}
|
|
|
|
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
int
|
|
|
|
sys_sigfastblock(struct thread *td, struct sigfastblock_args *uap)
|
|
|
|
{
|
|
|
|
struct proc *p;
|
|
|
|
int error, res;
|
|
|
|
uint32_t oldval;
|
|
|
|
|
|
|
|
error = 0;
|
2020-02-20 15:34:02 +00:00
|
|
|
p = td->td_proc;
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
switch (uap->cmd) {
|
|
|
|
case SIGFASTBLOCK_SETPTR:
|
|
|
|
if ((td->td_pflags & TDP_SIGFASTBLOCK) != 0) {
|
|
|
|
error = EBUSY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (((uintptr_t)(uap->ptr) & (sizeof(uint32_t) - 1)) != 0) {
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
td->td_pflags |= TDP_SIGFASTBLOCK;
|
|
|
|
td->td_sigblock_ptr = uap->ptr;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SIGFASTBLOCK_UNBLOCK:
|
2020-02-20 15:34:02 +00:00
|
|
|
if ((td->td_pflags & TDP_SIGFASTBLOCK) == 0) {
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
2020-02-20 15:34:02 +00:00
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
res = casueword32(td->td_sigblock_ptr,
|
|
|
|
SIGFASTBLOCK_PEND, &oldval, 0);
|
|
|
|
if (res == -1) {
|
|
|
|
error = EFAULT;
|
|
|
|
sigfastblock_failed(td, false, true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (res == 0)
|
|
|
|
break;
|
|
|
|
MPASS(res == 1);
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
if (oldval != SIGFASTBLOCK_PEND) {
|
|
|
|
error = EBUSY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
error = thread_check_susp(td, false);
|
|
|
|
if (error != 0)
|
|
|
|
break;
|
|
|
|
}
|
2020-02-20 15:34:02 +00:00
|
|
|
if (error != 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* td_sigblock_val is cleared there, but not on a
|
|
|
|
* syscall exit. The end effect is that a single
|
|
|
|
* interruptible sleep, while user sigblock word is
|
|
|
|
* set, might return EINTR or ERESTART to usermode
|
|
|
|
* without delivering signal. All further sleeps,
|
|
|
|
* until userspace clears the word and does
|
|
|
|
* sigfastblock(UNBLOCK), observe current word and no
|
|
|
|
* longer get interrupted. It is slight
|
|
|
|
* non-conformance, with alternative to have read the
|
|
|
|
* sigblock word on each syscall entry.
|
|
|
|
*/
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
td->td_sigblock_val = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Rely on normal ast mechanism to deliver pending
|
|
|
|
* signals to current thread. But notify others about
|
|
|
|
* fake unblock.
|
|
|
|
*/
|
2020-05-11 22:38:32 +00:00
|
|
|
sigfastblock_resched(td, error == 0 && p->p_numthreads != 1);
|
|
|
|
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SIGFASTBLOCK_UNSETPTR:
|
|
|
|
if ((td->td_pflags & TDP_SIGFASTBLOCK) == 0) {
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
2020-02-20 15:34:02 +00:00
|
|
|
if (!sigfastblock_fetch_sig(td, false, &oldval)) {
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
error = EFAULT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (oldval != 0 && oldval != SIGFASTBLOCK_PEND) {
|
|
|
|
error = EBUSY;
|
|
|
|
break;
|
|
|
|
}
|
2020-02-20 15:34:02 +00:00
|
|
|
sigfastblock_clear(td);
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-20 15:34:02 +00:00
|
|
|
sigfastblock_clear(struct thread *td)
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
{
|
2020-02-20 15:34:02 +00:00
|
|
|
bool resched;
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
|
|
|
|
if ((td->td_pflags & TDP_SIGFASTBLOCK) == 0)
|
|
|
|
return;
|
2020-02-20 15:34:02 +00:00
|
|
|
td->td_sigblock_val = 0;
|
2020-03-10 20:25:03 +00:00
|
|
|
resched = (td->td_pflags & TDP_SIGFASTPENDING) != 0 ||
|
|
|
|
SIGPENDING(td);
|
2020-02-20 15:34:02 +00:00
|
|
|
td->td_pflags &= ~(TDP_SIGFASTBLOCK | TDP_SIGFASTPENDING);
|
2020-05-11 22:38:32 +00:00
|
|
|
sigfastblock_resched(td, resched);
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-20 15:34:02 +00:00
|
|
|
sigfastblock_fetch(struct thread *td)
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
{
|
2020-02-20 15:34:02 +00:00
|
|
|
uint32_t val;
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
|
2020-02-20 15:34:02 +00:00
|
|
|
(void)sigfastblock_fetch_sig(td, true, &val);
|
|
|
|
}
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
|
2020-03-10 20:04:38 +00:00
|
|
|
static void
|
|
|
|
sigfastblock_setpend1(struct thread *td)
|
2020-02-20 15:34:02 +00:00
|
|
|
{
|
|
|
|
int res;
|
|
|
|
uint32_t oldval;
|
|
|
|
|
|
|
|
if ((td->td_pflags & TDP_SIGFASTBLOCK) == 0)
|
|
|
|
return;
|
|
|
|
res = fueword32((void *)td->td_sigblock_ptr, &oldval);
|
|
|
|
if (res == -1) {
|
|
|
|
sigfastblock_failed(td, true, false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (;;) {
|
|
|
|
res = casueword32(td->td_sigblock_ptr, oldval, &oldval,
|
|
|
|
oldval | SIGFASTBLOCK_PEND);
|
|
|
|
if (res == -1) {
|
|
|
|
sigfastblock_failed(td, true, true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (res == 0) {
|
|
|
|
td->td_sigblock_val = oldval & ~SIGFASTBLOCK_FLAGS;
|
|
|
|
td->td_pflags &= ~TDP_SIGFASTPENDING;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
MPASS(res == 1);
|
|
|
|
if (thread_check_susp(td, false) != 0)
|
|
|
|
break;
|
|
|
|
}
|
Add a way to manage thread signal mask using shared word, instead of syscall.
A new syscall sigfastblock(2) is added which registers a uint32_t
variable as containing the count of blocks for signal delivery. Its
content is read by kernel on each syscall entry and on AST processing,
non-zero count of blocks is interpreted same as the signal mask
blocking all signals.
The biggest downside of the feature that I see is that memory
corruption that affects the registered fast sigblock location, would
cause quite strange application misbehavior. For instance, the process
would be immune to ^C (but killable by SIGKILL).
With consumers (rtld and libthr added), benchmarks do not show a
slow-down of the syscalls in micro-measurements, and macro benchmarks
like buildworld do not demonstrate a difference. Part of the reason is
that buildworld time is dominated by compiler, and clang already links
to libthr. On the other hand, small utilities typically used by shell
scripts have the total number of syscalls cut by half.
The syscall is not exported from the stable libc version namespace on
purpose. It is intended to be used only by our C runtime
implementation internals.
Tested by: pho
Disscussed with: cem, emaste, jilles
Sponsored by: The FreeBSD Foundation
Differential revision: https://reviews.freebsd.org/D12773
2020-02-09 11:53:12 +00:00
|
|
|
}
|
2020-03-10 20:04:38 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
sigfastblock_setpend(struct thread *td, bool resched)
|
|
|
|
{
|
|
|
|
struct proc *p;
|
|
|
|
|
|
|
|
sigfastblock_setpend1(td);
|
|
|
|
if (resched) {
|
|
|
|
p = td->td_proc;
|
|
|
|
PROC_LOCK(p);
|
|
|
|
reschedule_signals(p, fastblock_mask, SIGPROCMASK_FASTBLK);
|
|
|
|
PROC_UNLOCK(p);
|
|
|
|
}
|
|
|
|
}
|