Consolidate the multi-line console output in check_hung_task() into a new
helper function, hung_task_diagnostics().
This patch ensures the entire diagnostic block (task info, kernel
version, and sysctl advice) is logged to the ring buffer via a single
pr_err() call. This is critical in a concurrent environment to prevent
message lines from interleaving with other CPU activity, thus
maintaining contextual integrity of the warning message.
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
kernel/hung_task.c | 39 +++++++++++++++++++++++++++++----------
1 file changed, 29 insertions(+), 10 deletions(-)
diff --git a/kernel/hung_task.c b/kernel/hung_task.c
index d2254c91450b..6f3fb26378b5 100644
--- a/kernel/hung_task.c
+++ b/kernel/hung_task.c
@@ -223,6 +223,34 @@ static inline void debug_show_blocker(struct task_struct *task, unsigned long ti
}
#endif
+/**
+ * hung_task_diagnostics - Print structured diagnostic info for a hung task.
+ * @t: The struct task_struct of the detected hung task.
+ *
+ * This function consolidates the printing of core diagnostic information
+ * for a task found to be blocked. This approach ensures atomic logging
+ * of the multi-line message block, preventing interleaving by other
+ * console activity, thus maintaining contextual clarity.
+ */
+static inline void hung_task_diagnostics(struct task_struct *t)
+{
+ unsigned long blocked_secs = (jiffies - t->last_switch_time) / HZ;
+ const char *coredump_msg = "";
+ const char *disable_msg =
+ "\"echo 0 > /proc/sys/kernel/hung_task_timeout_secs\""
+ " disables this message.\n";
+
+ if (t->flags & PF_POSTCOREDUMP)
+ coredump_msg = " Blocked by coredump.\n";
+
+ pr_err("INFO: task %s:%d blocked for more than %ld seconds.\n"
+ " %s %s %.*s\n%s%s",
+ t->comm, t->pid, blocked_secs,
+ print_tainted(), init_utsname()->release,
+ (int)strcspn(init_utsname()->version, " "),
+ init_utsname()->version, coredump_msg, disable_msg);
+}
+
static void check_hung_task(struct task_struct *t, unsigned long timeout,
unsigned long prev_detect_count)
{
@@ -252,16 +280,7 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout,
if (sysctl_hung_task_warnings || hung_task_call_panic) {
if (sysctl_hung_task_warnings > 0)
sysctl_hung_task_warnings--;
- pr_err("INFO: task %s:%d blocked for more than %ld seconds.\n",
- t->comm, t->pid, (jiffies - t->last_switch_time) / HZ);
- pr_err(" %s %s %.*s\n",
- print_tainted(), init_utsname()->release,
- (int)strcspn(init_utsname()->version, " "),
- init_utsname()->version);
- if (t->flags & PF_POSTCOREDUMP)
- pr_err(" Blocked by coredump.\n");
- pr_err("\"echo 0 > /proc/sys/kernel/hung_task_timeout_secs\""
- " disables this message.\n");
+ hung_task_diagnostics(t);
sched_show_task(t);
debug_show_blocker(t, timeout);
--
2.51.0
On Wed, Dec 10, 2025 at 10:30:03PM -0500, Aaron Tomlin wrote: > Consolidate the multi-line console output in check_hung_task() into a new > helper function, hung_task_diagnostics(). > > This patch ensures the entire diagnostic block (task info, kernel > version, and sysctl advice) is logged to the ring buffer via a single > pr_err() call. This is critical in a concurrent environment to prevent > message lines from interleaving with other CPU activity, thus > maintaining contextual integrity of the warning message. If this message is "critical", then it should not be going through the syslog as that is NOT a "critical" way to communicate things to userspace. What is currently breaking today with the multi-line message that you have? Why is this so much more special than the normal oops / warning / oom and other type messages that are multi-lines today? I'm all for moving this to a single function, but I'm not ok with multi-line messages in one pr_err() call like this, sorry. Especially one that contains a "here is how to disable this" message like this one does, that surely is NOT a "critical" thing. thanks, greg k-h
On Thu, Dec 11, 2025 at 05:02:08PM +0900, Greg KH wrote: > I'm all for moving this to a single function, but I'm not ok with > multi-line messages in one pr_err() call like this, sorry. Hi Greg, Thank you for your feedback on the patch. I agree with your assessment regarding the severity and the use of a single pr_err() call for multi-line output. My previous description of this message being "critical" was certainly an overstatement; this warning is not more critical than an Oops or an OOM report, which also manage multi-line output adequately. I will revert to the previous multi-line implementation but will still consolidate the logic into the new helper function and make some additional improvements to hopefully improve the code structure and readability somewhat. Kind regards, -- Aaron Tomlin
© 2016 - 2025 Red Hat, Inc.