Skip to content

Commit 3d86f20

Browse files
Tetsuo Handasfrothwell
authored andcommitted
kernel/hung_task.c: Monitor killed tasks.
syzbot's current top report is "no output from test machine" where the userspace process failed to spawn a new test process for 300 seconds for some reason. One of reasons which can result in this report is that an already spawned test process was unable to terminate (e.g. trapped at an unkillable retry loop due to some bug) after SIGKILL was sent to that process. Therefore, reporting when a thread is failing to terminate despite a fatal signal is pending would give us more useful information. In the context of syzbot's testing where there are only 2 CPUs in the target VM (which means that only small number of threads and not so much memory) and threads get SIGKILL after 5 seconds from fork(), being unable to reach do_exit() within 10 seconds is likely a sign of something went wrong. Therefore, I would like to try this patch in linux-next.git for feasibility testing whether this patch helps finding more bugs and reproducers for such bugs, by bringing "unable to terminate threads" reports out of "no output from test machine" reports. Potential bad effect of this patch will be that kernel code becomes killable without addressing the root cause of being unable to terminate, for use of killable wait will bypass both TASK_UNINTERRUPTIBLE stall test and SIGKILL after 5 seconds behavior, which will result in failing to detect in real systems where SIGKILL won't be sent after 5 seconds when something went wrong. This version shares existing sysctl settings (e.g. check interval, timeout, whether to panic) used for detecting TASK_UNINTERRUPTIBLE threads. We will likely want to use different sysctl settings for monitoring killed threads. But let's start as linux-next.git patch without introducing new sysctl settings. We can add sysctl settings before sending to linux.git. Link: http://lkml.kernel.org/r/60d1d7f6-b201-3dcb-a51b-76a31bcfa919@i-love.sakura.ne.jp Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Petr Mladek <pmladek@suse.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: "Paul E. McKenney" <paulmck@kernel.org> Cc: Vitaly Kuznetsov <vkuznets@redhat.com> Cc: Liu Chuansheng <chuansheng.liu@intel.com> Cc: Valdis Kletnieks <valdis.kletnieks@vt.edu> Cc: linux-kernel@vger.kernel.org Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
1 parent 586322e commit 3d86f20

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

include/linux/sched.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,7 @@ struct task_struct {
905905
#ifdef CONFIG_DETECT_HUNG_TASK
906906
unsigned long last_switch_count;
907907
unsigned long last_switch_time;
908+
unsigned long killed_time;
908909
#endif
909910
/* Filesystem information: */
910911
struct fs_struct *fs;

kernel/hung_task.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,47 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
142142
touch_nmi_watchdog();
143143
}
144144

145+
static void check_killed_task(struct task_struct *t, unsigned long timeout)
146+
{
147+
unsigned long stamp = t->killed_time;
148+
149+
/*
150+
* Ensure the task is not frozen.
151+
* Also, skip vfork and any other user process that freezer should skip.
152+
*/
153+
if (unlikely(t->flags & (PF_FROZEN | PF_FREEZER_SKIP)))
154+
return;
155+
/*
156+
* Skip threads which are already inside do_exit(), for exit_mm() etc.
157+
* might take many seconds.
158+
*/
159+
if (t->flags & PF_EXITING)
160+
return;
161+
if (!stamp) {
162+
stamp = jiffies;
163+
if (!stamp)
164+
stamp++;
165+
t->killed_time = stamp;
166+
return;
167+
}
168+
if (time_is_after_jiffies(stamp + timeout * HZ))
169+
return;
170+
trace_sched_process_hang(t);
171+
if (sysctl_hung_task_panic) {
172+
console_verbose();
173+
hung_task_call_panic = true;
174+
}
175+
/*
176+
* This thread failed to terminate for more than
177+
* sysctl_hung_task_timeout_secs seconds, complain:
178+
*/
179+
pr_err("INFO: task %s:%d can't die for more than %ld seconds.\n",
180+
t->comm, t->pid, (jiffies - stamp) / HZ);
181+
sched_show_task(t);
182+
hung_task_show_lock = true;
183+
touch_nmi_watchdog();
184+
}
185+
145186
/*
146187
* To avoid extending the RCU grace period for an unbounded amount of time,
147188
* periodically exit the critical section and enter a new one.
@@ -193,6 +234,9 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
193234
goto unlock;
194235
last_break = jiffies;
195236
}
237+
/* Check threads which are about to terminate. */
238+
if (unlikely(fatal_signal_pending(t)))
239+
check_killed_task(t, timeout);
196240
/* use "==" to skip the TASK_KILLABLE tasks waiting on NFS */
197241
if (t->state == TASK_UNINTERRUPTIBLE)
198242
check_hung_task(t, timeout);

0 commit comments

Comments
 (0)