* Re: [PATCH v6 6/6] signal: Don't restart fork when signals come in. [not found] <201808101434273569497@zte.com.cn> @ 2018-08-10 12:15 ` Eric W. Biederman 0 siblings, 0 replies; 2+ messages in thread From: Eric W. Biederman @ 2018-08-10 12:15 UTC (permalink / raw) To: wen.yang99 Cc: torvalds, oleg, akpm, linux-kernel, ma.jiang, chen.shengyuan, zhong.weidong <wen.yang99@zte.com.cn> writes: > ebiederm@xmission.com <ebiederm@xmission.com> writes >> Subject: [PATCH v6 6/6] signal: Don't restart fork when signals come in. >> >> Wen Yang <wen.yang99@zte.com.cn> and majiang <ma.jiang@zte.com.cn> >> report that a periodic signal received during fork can cause fork to >> continually restart preventing an application from making progress. >> >> ... >> diff --git a/kernel/signal.c b/kernel/signal.c >> index 9f0eafb6d474..cfa9d10e731a 100644 >> --- a/kernel/signal.c >> +++ b/kernel/signal.c >> @@ -1121,6 +1121,21 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, >> out_set: >> signalfd_notify(t, sig); >> sigaddset(&pending->signal, sig); >> + >> + /* Let multiprocess signals appear after on-going forks */ >> + if (type > PIDTYPE_TGID) { >> + struct multiprocess_signals *delayed; >> + hlist_for_each_entry(delayed, &t->signal->multiprocess, node) { >> + sigset_t *signal = &delayed->signal; >> + /* Can't queue both a stop and a continue signal */ >> + if (sig == SIGCONT) >> + sigdelsetmask(signal, SIG_KERNEL_STOP_MASK); >> + else if (sig_kernel_stop(sig)) >> + sigdelset(signal, SIGCONT); >> + sigaddset(signal, sig); >> + } >> + } >> + >> complete_signal(sig, t, type); >> ret: >> trace_signal_generate(sig, info, t, type != PIDTYPE_PID, result); > > I've migrated this patch and try to test it, but I ran into a compile error: > > kernel/signal.c: In function '__send_signal': > kernel/signal.c:1192:9: error: 'type' undeclared (first use in this function) > if (type > PIDTYPE_TGID) { > ^ > We may also need some patches, which pass pid type into > __send_signal. We most definitely need the the first 15 patches from my last series of patches that push the pid type down. I did not repeat them here because there is consensus that they are fine working fine. I have a branch with everything at: https://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git siginfo-testing Eric ^ permalink raw reply [flat|nested] 2+ messages in thread
* [PATCH v5 0/6] Not restarting for due to signals.
@ 2018-08-09 6:53 Eric W. Biederman
2018-08-09 6:56 ` [PATCH v5 6/6] signal: Don't restart fork when signals come in Eric W. Biederman
0 siblings, 1 reply; 2+ messages in thread
From: Eric W. Biederman @ 2018-08-09 6:53 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Andrew Morton, linux-kernel, Wen Yang, majiang, Linus Torvalds
This builds on patches 1-15 of my previous patch posting. As those are
non-controversial I am not posting them again.
I took longer than I had hoped to get this set together because a kernel
testing robot noticed some random corruption with the way I had been
adding to the list. I finally tracked it down to failing to remove the
sigset from the list during fork_idle. So I have made that logic
simpler and use hlist_del_init which will only remove an item from a
list if it was placed on the list in the first place.
I took Oleg's suggesting and moved calculate_sigpending into
schedule_tail where recalc_sigpending an be used directly. Then in
calculate_sigpending I just unconditionally set TIF_SIGPENDING and allow
recalc_sigpending to clear TIF_SIGPENDING if we don't need it.
I also now handle the stop/continue signal magic where we only let one
of stop signals and SIGCONT be pending at a time. Looking at it from
first principles dropping one of SIGTSTP SIGTTIN SIGTTOU or SIGCONT
before calling it's handler feels wrong. I checked and it is our
historical behavior, so I won't even thinking of introducing different
behavior at this point.
Eric W. Biederman (6):
fork: Move and describe why the code examines PIDNS_ADDING
fork: Unconditionally exit if a fatal signal is pending
signal: Add calculate_sigpending()
fork: Skip setting TIF_SIGPENDING in ptrace_init_task
fork: Have new threads join on-going signal group stops
signal: Don't restart fork when signals come in.
include/linux/ptrace.h | 2 --
include/linux/sched/signal.h | 11 ++++++++++
init/init_task.c | 1 +
kernel/fork.c | 49 ++++++++++++++++++++++++++++++--------------
kernel/sched/core.c | 2 ++
kernel/signal.c | 43 ++++++++++++++++++++++++++++++++++++++
6 files changed, 91 insertions(+), 17 deletions(-)
Eric
^ permalink raw reply [flat|nested] 2+ messages in thread* [PATCH v5 6/6] signal: Don't restart fork when signals come in. 2018-08-09 6:53 [PATCH v5 0/6] Not restarting for due to signals Eric W. Biederman @ 2018-08-09 6:56 ` Eric W. Biederman 2018-08-09 17:15 ` Linus Torvalds 0 siblings, 1 reply; 2+ messages in thread From: Eric W. Biederman @ 2018-08-09 6:56 UTC (permalink / raw) To: Oleg Nesterov Cc: Andrew Morton, linux-kernel, Wen Yang, majiang, Linus Torvalds, Eric W. Biederman Wen Yang <wen.yang99@zte.com.cn> and majiang <ma.jiang@zte.com.cn> report that a periodic signal received during fork can cause fork to continually restart preventing an application from making progress. The code was being overly pesimistic. Fork needs to guarantee that a signal sent to multiple processes is logically delivered before the fork and just to the forking process or logically delivered after the fork to both the forking process and it's newly spawned child. For signals like periodic timers that are always delivered to a single process fork can safely complete and let them appear to logically delivered after the fork(). While examining this issue I also discovered that fork today will miss signals delivered to multiple processes during the fork and handled by another thread. Similarly the current code will also miss blocked signals that are delivered to multiple process, as those signals will not appear pending during fork. Add a list of each thread that is currently forking, and keep on that list a signal set that records all of the signals sent to multiple processes. When fork completes initialize the new processes shared_pending signal set with it. The calculate_sigpending function will see those signals and set TIF_SIGPENDING causing the new task to take the slow path to userspace to handle those signals. Making it appear as if those signals were received immediately after the fork. It is not possible to send real time signals to multiple processes and exceptions don't go to multiple processes, which means that that are no signals sent to multiple processes that require siginfo. This means it is safe to not bother collecting siginfo on signals sent during fork. The sigaction of a child of fork is initially the same as the sigaction of the parent process. So a signal the parent ignores the child will also initially ignore. Therefore it is safe to ignore signals sent to multiple processes and ignored by the forking process. Signals sent to only a single process or only a single thread and delivered during fork are treated as if they are received after the fork, and generally not dealt with. They won't cause any problems. V2: Added removal from the multiprocess list on failure. V3: Use -ERESTARTNOINTR directly V4: - Don't queue both SIGCONT and SIGSTOP - Initialize signal_struct.multiprocess in init_task - Move setting of shared_pending to before the new task is visible to signals. This prevents signals from comming in before shared_pending.signal is set to delayed.signal and being lost. V5: - rework list add and delete to account for idle threads Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=200447 Reported-by: Wen Yang <wen.yang99@zte.com.cn> and Reported-by: majiang <ma.jiang@zte.com.cn> Fixes: 4a2c7a7837da ("[PATCH] make fork() atomic wrt pgrp/session signals") Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> --- include/linux/sched/signal.h | 8 +++++++ init/init_task.c | 1 + kernel/fork.c | 43 +++++++++++++++++++++--------------- kernel/signal.c | 18 +++++++++++++++ 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index ae2b0b81be25..4e9b77fb702d 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -69,6 +69,11 @@ struct thread_group_cputimer { bool checking_timer; }; +struct multiprocess_signals { + sigset_t signal; + struct hlist_node node; +}; + /* * NOTE! "signal_struct" does not have its own * locking, because a shared signal_struct always @@ -90,6 +95,9 @@ struct signal_struct { /* shared signal handling: */ struct sigpending shared_pending; + /* For collecting multiprocess signals during fork */ + struct hlist_head multiprocess; + /* thread group exit support */ int group_exit_code; /* overloaded: diff --git a/init/init_task.c b/init/init_task.c index 4f97846256d7..5aebe3be4d7c 100644 --- a/init/init_task.c +++ b/init/init_task.c @@ -22,6 +22,7 @@ static struct signal_struct init_signals = { .list = LIST_HEAD_INIT(init_signals.shared_pending.list), .signal = {{0}} }, + .multiprocess = HLIST_HEAD_INIT, .rlim = INIT_RLIMITS, .cred_guard_mutex = __MUTEX_INITIALIZER(init_signals.cred_guard_mutex), #ifdef CONFIG_POSIX_TIMERS diff --git a/kernel/fork.c b/kernel/fork.c index ab731e15a600..411e34acace7 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1456,6 +1456,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) init_waitqueue_head(&sig->wait_chldexit); sig->curr_target = tsk; init_sigpending(&sig->shared_pending); + INIT_HLIST_HEAD(&sig->multiprocess); seqlock_init(&sig->stats_lock); prev_cputime_init(&sig->prev_cputime); @@ -1602,6 +1603,7 @@ static __latent_entropy struct task_struct *copy_process( { int retval; struct task_struct *p; + struct multiprocess_signals delayed; /* * Don't allow sharing the root directory with processes in a different @@ -1649,6 +1651,24 @@ static __latent_entropy struct task_struct *copy_process( return ERR_PTR(-EINVAL); } + /* + * Force any signals received before this point to be delivered + * before the fork happens. Collect up signals sent to multiple + * processes that happen during the fork and delay them so that + * they appear to happen after the fork. + */ + sigemptyset(&delayed.signal); + INIT_HLIST_NODE(&delayed.node); + + spin_lock_irq(¤t->sighand->siglock); + if (!(clone_flags & CLONE_THREAD)) + hlist_add_head(&delayed.node, ¤t->signal->multiprocess); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + retval = -ERESTARTNOINTR; + if (signal_pending(current)) + goto fork_out; + retval = -ENOMEM; p = dup_task_struct(current, node); if (!p) @@ -1934,22 +1954,6 @@ static __latent_entropy struct task_struct *copy_process( goto bad_fork_cancel_cgroup; } - if (!(clone_flags & CLONE_THREAD)) { - /* - * Process group and session signals need to be delivered to just the - * parent before the fork or both the parent and the child after the - * fork. Restart if a signal comes in before we add the new process to - * it's process group. - * A fatal signal pending means that current will exit, so the new - * thread can't slip out of an OOM kill (or normal SIGKILL). - */ - recalc_sigpending(); - if (signal_pending(current)) { - retval = -ERESTARTNOINTR; - goto bad_fork_cancel_cgroup; - } - } - init_task_pid_links(p); if (likely(p->pid)) { @@ -1965,7 +1969,7 @@ static __latent_entropy struct task_struct *copy_process( ns_of_pid(pid)->child_reaper = p; p->signal->flags |= SIGNAL_UNKILLABLE; } - + p->signal->shared_pending.signal = delayed.signal; p->signal->tty = tty_kref_get(current->signal->tty); /* * Inherit has_child_subreaper flag under the same @@ -1993,8 +1997,8 @@ static __latent_entropy struct task_struct *copy_process( attach_pid(p, PIDTYPE_PID); nr_threads++; } - total_forks++; + hlist_del_init(&delayed.node); spin_unlock(¤t->sighand->siglock); syscall_tracepoint_update(p); write_unlock_irq(&tasklist_lock); @@ -2059,6 +2063,9 @@ static __latent_entropy struct task_struct *copy_process( put_task_stack(p); free_task(p); fork_out: + spin_lock_irq(¤t->sighand->siglock); + hlist_del_init(&delayed.node); + spin_unlock_irq(¤t->sighand->siglock); return ERR_PTR(retval); } diff --git a/kernel/signal.c b/kernel/signal.c index 9f0eafb6d474..850885db2c1e 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1121,6 +1121,24 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, out_set: signalfd_notify(t, sig); sigaddset(&pending->signal, sig); + + /* Let multiprocess signals appear after on-going forks */ + if (type > PIDTYPE_TGID) { + struct multiprocess_signals *delayed; + hlist_for_each_entry(delayed, &t->signal->multiprocess, node) { + sigset_t *signal = &delayed->signal; + /* Can't queue both a stop and a continue signal */ + if (sig == SIGCONT) { + sigset_t flush; + siginitset(&flush, SIG_KERNEL_STOP_MASK); + sigandnsets(signal, signal, &flush); + } else if (sig_kernel_stop(sig)) { + sigdelset(signal, SIGCONT); + } + sigaddset(signal, sig); + } + } + complete_signal(sig, t, type); ret: trace_signal_generate(sig, info, t, type != PIDTYPE_PID, result); -- 2.17.1 ^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v5 6/6] signal: Don't restart fork when signals come in. 2018-08-09 6:56 ` [PATCH v5 6/6] signal: Don't restart fork when signals come in Eric W. Biederman @ 2018-08-09 17:15 ` Linus Torvalds 2018-08-09 18:09 ` [PATCH v6 " Eric W. Biederman 0 siblings, 1 reply; 2+ messages in thread From: Linus Torvalds @ 2018-08-09 17:15 UTC (permalink / raw) To: Eric W. Biederman Cc: Oleg Nesterov, Andrew Morton, Linux Kernel Mailing List, Wen Yang, majiang On Wed, Aug 8, 2018 at 11:57 PM Eric W. Biederman <ebiederm@xmission.com> wrote: > > The code was being overly pesimistic. Pessimistic. > + if (type > PIDTYPE_TGID) { > + struct multiprocess_signals *delayed; > + hlist_for_each_entry(delayed, &t->signal->multiprocess, node) { > + sigset_t *signal = &delayed->signal; > + /* Can't queue both a stop and a continue signal */ > + if (sig == SIGCONT) { > + sigset_t flush; > + siginitset(&flush, SIG_KERNEL_STOP_MASK); > + sigandnsets(signal, signal, &flush); This looks odd and unnecessary. Why isn't this just a sigdelsetmask(signal, SIG_KERNEL_STOP_MASK); since all of the traditional stop bits should be in the low mask. I see that we apparently have this stupid pattern elsewhere too, and it looks like it's because we stupidly say "are the RT signals in the non-legacy set", when that definitely cannot be the case for the (very much legacy) tty flow control signals. Linus ^ permalink raw reply [flat|nested] 2+ messages in thread
* [PATCH v6 6/6] signal: Don't restart fork when signals come in. 2018-08-09 17:15 ` Linus Torvalds @ 2018-08-09 18:09 ` Eric W. Biederman 0 siblings, 0 replies; 2+ messages in thread From: Eric W. Biederman @ 2018-08-09 18:09 UTC (permalink / raw) To: Linus Torvalds Cc: Oleg Nesterov, Andrew Morton, Linux Kernel Mailing List, Wen Yang, majiang Wen Yang <wen.yang99@zte.com.cn> and majiang <ma.jiang@zte.com.cn> report that a periodic signal received during fork can cause fork to continually restart preventing an application from making progress. The code was being overly pessimistic. Fork needs to guarantee that a signal sent to multiple processes is logically delivered before the fork and just to the forking process or logically delivered after the fork to both the forking process and it's newly spawned child. For signals like periodic timers that are always delivered to a single process fork can safely complete and let them appear to logically delivered after the fork(). While examining this issue I also discovered that fork today will miss signals delivered to multiple processes during the fork and handled by another thread. Similarly the current code will also miss blocked signals that are delivered to multiple process, as those signals will not appear pending during fork. Add a list of each thread that is currently forking, and keep on that list a signal set that records all of the signals sent to multiple processes. When fork completes initialize the new processes shared_pending signal set with it. The calculate_sigpending function will see those signals and set TIF_SIGPENDING causing the new task to take the slow path to userspace to handle those signals. Making it appear as if those signals were received immediately after the fork. It is not possible to send real time signals to multiple processes and exceptions don't go to multiple processes, which means that that are no signals sent to multiple processes that require siginfo. This means it is safe to not bother collecting siginfo on signals sent during fork. The sigaction of a child of fork is initially the same as the sigaction of the parent process. So a signal the parent ignores the child will also initially ignore. Therefore it is safe to ignore signals sent to multiple processes and ignored by the forking process. Signals sent to only a single process or only a single thread and delivered during fork are treated as if they are received after the fork, and generally not dealt with. They won't cause any problems. V2: Added removal from the multiprocess list on failure. V3: Use -ERESTARTNOINTR directly V4: - Don't queue both SIGCONT and SIGSTOP - Initialize signal_struct.multiprocess in init_task - Move setting of shared_pending to before the new task is visible to signals. This prevents signals from comming in before shared_pending.signal is set to delayed.signal and being lost. V5: - rework list add and delete to account for idle threads v6: - Use sigdelsetmask when removing stop signals Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=200447 Reported-by: Wen Yang <wen.yang99@zte.com.cn> and Reported-by: majiang <ma.jiang@zte.com.cn> Fixes: 4a2c7a7837da ("[PATCH] make fork() atomic wrt pgrp/session signals") Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> --- include/linux/sched/signal.h | 8 +++++++ init/init_task.c | 1 + kernel/fork.c | 43 +++++++++++++++++++++--------------- kernel/signal.c | 15 +++++++++++++ 4 files changed, 49 insertions(+), 18 deletions(-) diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index ae2b0b81be25..4e9b77fb702d 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -69,6 +69,11 @@ struct thread_group_cputimer { bool checking_timer; }; +struct multiprocess_signals { + sigset_t signal; + struct hlist_node node; +}; + /* * NOTE! "signal_struct" does not have its own * locking, because a shared signal_struct always @@ -90,6 +95,9 @@ struct signal_struct { /* shared signal handling: */ struct sigpending shared_pending; + /* For collecting multiprocess signals during fork */ + struct hlist_head multiprocess; + /* thread group exit support */ int group_exit_code; /* overloaded: diff --git a/init/init_task.c b/init/init_task.c index 4f97846256d7..5aebe3be4d7c 100644 --- a/init/init_task.c +++ b/init/init_task.c @@ -22,6 +22,7 @@ static struct signal_struct init_signals = { .list = LIST_HEAD_INIT(init_signals.shared_pending.list), .signal = {{0}} }, + .multiprocess = HLIST_HEAD_INIT, .rlim = INIT_RLIMITS, .cred_guard_mutex = __MUTEX_INITIALIZER(init_signals.cred_guard_mutex), #ifdef CONFIG_POSIX_TIMERS diff --git a/kernel/fork.c b/kernel/fork.c index ab731e15a600..411e34acace7 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1456,6 +1456,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) init_waitqueue_head(&sig->wait_chldexit); sig->curr_target = tsk; init_sigpending(&sig->shared_pending); + INIT_HLIST_HEAD(&sig->multiprocess); seqlock_init(&sig->stats_lock); prev_cputime_init(&sig->prev_cputime); @@ -1602,6 +1603,7 @@ static __latent_entropy struct task_struct *copy_process( { int retval; struct task_struct *p; + struct multiprocess_signals delayed; /* * Don't allow sharing the root directory with processes in a different @@ -1649,6 +1651,24 @@ static __latent_entropy struct task_struct *copy_process( return ERR_PTR(-EINVAL); } + /* + * Force any signals received before this point to be delivered + * before the fork happens. Collect up signals sent to multiple + * processes that happen during the fork and delay them so that + * they appear to happen after the fork. + */ + sigemptyset(&delayed.signal); + INIT_HLIST_NODE(&delayed.node); + + spin_lock_irq(¤t->sighand->siglock); + if (!(clone_flags & CLONE_THREAD)) + hlist_add_head(&delayed.node, ¤t->signal->multiprocess); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + retval = -ERESTARTNOINTR; + if (signal_pending(current)) + goto fork_out; + retval = -ENOMEM; p = dup_task_struct(current, node); if (!p) @@ -1934,22 +1954,6 @@ static __latent_entropy struct task_struct *copy_process( goto bad_fork_cancel_cgroup; } - if (!(clone_flags & CLONE_THREAD)) { - /* - * Process group and session signals need to be delivered to just the - * parent before the fork or both the parent and the child after the - * fork. Restart if a signal comes in before we add the new process to - * it's process group. - * A fatal signal pending means that current will exit, so the new - * thread can't slip out of an OOM kill (or normal SIGKILL). - */ - recalc_sigpending(); - if (signal_pending(current)) { - retval = -ERESTARTNOINTR; - goto bad_fork_cancel_cgroup; - } - } - init_task_pid_links(p); if (likely(p->pid)) { @@ -1965,7 +1969,7 @@ static __latent_entropy struct task_struct *copy_process( ns_of_pid(pid)->child_reaper = p; p->signal->flags |= SIGNAL_UNKILLABLE; } - + p->signal->shared_pending.signal = delayed.signal; p->signal->tty = tty_kref_get(current->signal->tty); /* * Inherit has_child_subreaper flag under the same @@ -1993,8 +1997,8 @@ static __latent_entropy struct task_struct *copy_process( attach_pid(p, PIDTYPE_PID); nr_threads++; } - total_forks++; + hlist_del_init(&delayed.node); spin_unlock(¤t->sighand->siglock); syscall_tracepoint_update(p); write_unlock_irq(&tasklist_lock); @@ -2059,6 +2063,9 @@ static __latent_entropy struct task_struct *copy_process( put_task_stack(p); free_task(p); fork_out: + spin_lock_irq(¤t->sighand->siglock); + hlist_del_init(&delayed.node); + spin_unlock_irq(¤t->sighand->siglock); return ERR_PTR(retval); } diff --git a/kernel/signal.c b/kernel/signal.c index 9f0eafb6d474..cfa9d10e731a 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1121,6 +1121,21 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, out_set: signalfd_notify(t, sig); sigaddset(&pending->signal, sig); + + /* Let multiprocess signals appear after on-going forks */ + if (type > PIDTYPE_TGID) { + struct multiprocess_signals *delayed; + hlist_for_each_entry(delayed, &t->signal->multiprocess, node) { + sigset_t *signal = &delayed->signal; + /* Can't queue both a stop and a continue signal */ + if (sig == SIGCONT) + sigdelsetmask(signal, SIG_KERNEL_STOP_MASK); + else if (sig_kernel_stop(sig)) + sigdelset(signal, SIGCONT); + sigaddset(signal, sig); + } + } + complete_signal(sig, t, type); ret: trace_signal_generate(sig, info, t, type != PIDTYPE_PID, result); -- 2.17.1 ^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2018-08-10 12:15 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <201808101434273569497@zte.com.cn>
2018-08-10 12:15 ` [PATCH v6 6/6] signal: Don't restart fork when signals come in Eric W. Biederman
2018-08-09 6:53 [PATCH v5 0/6] Not restarting for due to signals Eric W. Biederman
2018-08-09 6:56 ` [PATCH v5 6/6] signal: Don't restart fork when signals come in Eric W. Biederman
2018-08-09 17:15 ` Linus Torvalds
2018-08-09 18:09 ` [PATCH v6 " Eric W. Biederman
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox