From: Willy Tarreau Date: Mon, 24 Feb 2025 10:43:15 +0000 (+0100) Subject: BUG/MEDIUM: stream: don't use localtime in dumps from a signal handler X-Git-Tag: v3.2-dev7~67 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2e0bac90da0013513969224db94661dda88d7b98;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: stream: don't use localtime in dumps from a signal handler 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. --- diff --git a/src/stream.c b/src/stream.c index 5acb01ed9..b0b04a71a 100644 --- a/src/stream.c +++ b/src/stream.c @@ -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));