]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: stream: don't use localtime in dumps from a signal handler
authorWilly Tarreau <w@1wt.eu>
Mon, 24 Feb 2025 10:43:15 +0000 (11:43 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 24 Feb 2025 12:40:42 +0000 (13:40 +0100)
In issue #2861, Jarosaw Rzeszótko reported another issue with
"show threads", this time in relation with the conversion of a stream's
accept date to local time. Indeed, if the libc was interrupted in this
same function, it could have been interrupted with a lock held, then
it's no longer possible to dump the date, and we face a deadlock.
This is easy to reproduce with logging enabled.

Let's detect we come from a signal handler and do not try to resolve
the time to localtime in this case.

src/stream.c

index 5acb01ed907ba7c4bcc859af9d94ebfce8fb50b7..b0b04a71a50d018af134d3828b4c6286721a17ca 100644 (file)
@@ -3272,14 +3272,25 @@ static void __strm_dump_to_buffer(struct buffer *buf, const struct show_sess_ctx
 
        pfx = pfx ? pfx : "";
 
-       get_localtime(strm->logs.accept_date.tv_sec, &tm);
-       chunk_appendf(buf,
-                    "%p: [%02d/%s/%04d:%02d:%02d:%02d.%06d] id=%u proto=%s",
-                    strm,
-                    tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
-                    tm.tm_hour, tm.tm_min, tm.tm_sec, (int)(strm->logs.accept_date.tv_usec),
-                    strm->uniq_id,
-                    strm_li(strm) ? strm_li(strm)->rx.proto->name : "?");
+       if (th_ctx->flags & TH_FL_IN_ANY_HANDLER) {
+               /* avoid calling localtime_r() to avoid a risk of deadlock if we
+                * interrupted libc for example, cf
+                * https://github.com/haproxy/haproxy/issues/2861#issuecomment-2677761037
+                */
+               chunk_appendf(buf, "%p: [%lu.%06lu]", strm,
+                             (ulong)strm->logs.accept_date.tv_sec,
+                             (ulong)strm->logs.accept_date.tv_usec);
+       } else {
+               get_localtime(strm->logs.accept_date.tv_sec, &tm);
+               chunk_appendf(buf,
+                             "%p: [%02d/%s/%04d:%02d:%02d:%02d.%06lu]",
+                             strm,
+                             tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
+                             tm.tm_hour, tm.tm_min, tm.tm_sec, (ulong)strm->logs.accept_date.tv_usec);
+       }
+
+       chunk_appendf(buf, " id=%u proto=%s",
+                    strm->uniq_id, strm_li(strm) ? strm_li(strm)->rx.proto->name : "?");
 
        conn = objt_conn(strm_orig(strm));