From nobody Tue Jun 30 16:59:38 2026 X-Original-To: threads@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gqTs70qmPz6jVm5 for ; Tue, 30 Jun 2026 16:59:39 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gqTs64LQVz3lrV for ; Tue, 30 Jun 2026 16:59:38 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782838778; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Ft4Cpgi65/cUooWIClOEmIorW1bthA9WWyVO0j4sDo4=; b=Sav36Lb58bFNaSiU7QJF0hXo2369J8CifiZRMddkMn2moWaOAPvzS9feXfKSmzvqp6a9Ch 3frIM0pMG1VuH2oDzOT/TsVPJhpi0/0mJS2EvdewlNslgHwRCCHLI7mYzs63uJ9NpF1Xfd fplHDNoCrv2XhEzqwRjRjWnudZoFRAkhppSzW4TGMq5h9EhQDCfnP8IMXH8tZecYBb07Fc yWl2xYJ9ptBP7g7yXyrAD5XHSSzLaKrQx4kNbG9B0YlvwPPyzp/YFykju2GvIgViI70Xgv WiI+xbzRLJ6dxZqkffzY+hhF3tXGxlhSeM/5BcgPXpGoHJNuTKwP4mtS2+RrSw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1782838778; a=rsa-sha256; cv=none; b=vLVfXOirfy9mEKV6FN7CE2wnA5r/irGpJXYG/ZAA5jx8d0O9WpJMaRi4y4blaHhwL3VhCs tk4u2a7bYqSlQ71VnvTOjtW0X+/OLxDG/++4EowhQnRjR4Rpovz9tr95y7wGSisdofh1EV LKGx1WkfwYMMPV7MHs1dGwerPrd7T5lkrQRtjUvqUVk3Ltwmxu0WX0FQ01XEQewhUiDYYu 59JfOEPHfTyxhJXvSOP1KSeFUCPkbfaMSr9WnNjobma9OHtM+0ykWG6/v1tIJ7ZMdf2Ue1 Yr0nytbTFg1QsfrTew6kV0woOHV7y9NrMlNNroT2NDcZXoPYPzBt8tqCQbqpVA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782838778; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Ft4Cpgi65/cUooWIClOEmIorW1bthA9WWyVO0j4sDo4=; b=tzL+wmETWQaton9sJBiwZnETu3YmwDVNG/q+uyRGCltwkDtDjCB99N/tNVGGbtfMnzNkDE 3OdEyySbj0INaG8oGLYfoz+nkPEsLNJdq2Xdf81LZATNpvCvi9yS9pNY4IbDEfkZ4zbk5s 1T7mDetwh4G9MJq9k5U5DSGYsNmwpPmVLB5bRWZ/GcghgwbGEwzx6S7mA5ZJYr4oUDR7/n BW7Q1ZXcc8R/WSliCxN0FaH3JQCV0hS9Beiy0dZXFEFRp2KAHmtX0U/tUUpFKdur/mW70q Kf2OfOu3CXSlwRzi24PxiZQtHkPBb/k4mDL/no9r/WGC/sgknTJtHxFK0zoMXQ== Received: from kenobi.freebsd.org (kenobi.freebsd.org [IPv6:2610:1c1:1:606c::50:1d]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4gqTs63RTJzsll for ; Tue, 30 Jun 2026 16:59:38 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from kenobi.freebsd.org ([127.0.1.5]) by kenobi.freebsd.org (8.15.2/8.15.2) with ESMTP id 65UGxcwG072830 for ; Tue, 30 Jun 2026 16:59:38 GMT (envelope-from bugzilla-noreply@freebsd.org) Received: (from www@localhost) by kenobi.freebsd.org (8.15.2/8.15.2/Submit) id 65UGxcpR072829 for threads@FreeBSD.org; Tue, 30 Jun 2026 16:59:38 GMT (envelope-from bugzilla-noreply@freebsd.org) X-Authentication-Warning: kenobi.freebsd.org: www set sender to bugzilla-noreply@freebsd.org using -f From: bugzilla-noreply@freebsd.org To: threads@FreeBSD.org Subject: [Bug 296410] sprintf/vfprintf not thread safe on AArch64 due to localeconv_l using atomic_store_int, with relaxed semantics Date: Tue, 30 Jun 2026 16:59:38 +0000 X-Bugzilla-Reason: AssignedTo X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: Base System X-Bugzilla-Component: threads X-Bugzilla-Version: 14.4-RELEASE X-Bugzilla-Keywords: X-Bugzilla-Severity: Affects Some People X-Bugzilla-Who: tomas@vondra.me X-Bugzilla-Status: New X-Bugzilla-Resolution: X-Bugzilla-Priority: --- X-Bugzilla-Assigned-To: threads@FreeBSD.org X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version rep_platform op_sys bug_status bug_severity priority component assigned_to reporter Message-ID: Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="UTF-8" X-Bugzilla-URL: https://bugs.freebsd.org/bugzilla/ Auto-Submitted: auto-generated List-Id: Threading List-Archive: https://lists.freebsd.org/archives/freebsd-threads List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: freebsd-threads@freebsd.org Sender: owner-freebsd-threads@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D296410 Bug ID: 296410 Summary: sprintf/vfprintf not thread safe on AArch64 due to localeconv_l using atomic_store_int, with relaxed semantics Product: Base System Version: 14.4-RELEASE Hardware: arm64 OS: Any Status: New Severity: Affects Some People Priority: --- Component: threads Assignee: threads@FreeBSD.org Reporter: tomas@vondra.me While running tests (for ECPG in Postgres), we're getting occasional segfau= lts in tests using threads. This seems to affect only the AArch64 machine (whic= h is an rpi5), while the two x86_64 machines don't seem to have this issue. The crashes generally look like this: ------ Program terminated with signal SIGSEGV, Segmentation fault. Address not mapped to object. #0 __vfprintf (fp=3Dfp@entry=3D0x889dab00, locale=3Dlocale@entry=3D0x841df= cf0 <__xlocale_global_locale>, serrno=3D0, fmt0=3Dfmt0@entry=3D0x20087a "Connection: %d", ap=3D...) at /usr/src/lib/libc/stdio/vfprintf.c:477 warning: 477 /usr/src/lib/libc/stdio/vfprintf.c: No such file or directo= ry [Current thread is 1 (LWP 933707)] (gdb) bt #0 __vfprintf (fp=3Dfp@entry=3D0x889dab00, locale=3Dlocale@entry=3D0x841df= cf0 <__xlocale_global_locale>, serrno=3D0, fmt0=3Dfmt0@entry=3D0x20087a "Connection: %d", ap=3D...) at /usr/src/lib/libc/stdio/vfprintf.c:477 #1 0x000000008411d434 in vsprintf_l (locale=3D0x841dfcf0 <__xlocale_global_locale>, ap=3D..., str=3D, fmt=3D) at /usr/src/lib/libc/stdio/vsprintf.c:61 #2 vsprintf (str=3D0x889daefc "", fmt=3D, ap=3D...) at /usr/src/lib/libc/stdio/vsprintf.c:68 #3 0x00000000841123f4 in sprintf (str=3D0x0, str@entry=3D0x889daefc "", fmt=3D0x841dfcf0 <__xlocale_global_locale> "") at /usr/src/lib/libc/stdio/sprintf.c:56 #4 0x0000000000210ed8 in fn (arg=3D0x0) at prep.pgc:39 #5 0x00000000847844fc in thread_start (curthread=3D0x63044546d010) at /usr/src/lib/libthr/thread/thr_create.c:291 #6 0x0000000000000000 in ?? () ------ That is, it's a crash in vfprintf, on this line: decpt_len =3D (decimal_point[1] =3D=3D '\0' ? 1 : strlen(decimal_point)); After investigating a bit, I believe this is due to localeconv_l using atom= ics in relaxed mode when updating the decimal_point: if (atomic_load_acq_int(&loc->numeric_locale_changed) !=3D 0) { ... N_ASSIGN_STR(decimal_point); ... atomic_store_int(&loc->numeric_locale_changed, 0); } On architectures with weakly-ordered memory model (like the AArch64), this means the other threads may see the update to numeric_locale_changed, witho= ut seeing the updated decimal_point pointer. Which leads to the crash. This can be reproduced by a simple program: ------ #include #include void *fn(void *arg) { char buf[128]; for(int i=3D0; i<10000; i++) sprintf(buf, "%d", 1); return NULL; } int main() { pthread_t th[100]; for(int i=3D0; i<100; i++) pthread_create(&th[i], NULL, fn, NULL); for(int i=3D0; i<100; i++) pthread_join(th[i], NULL); return 0; } ------ It's a race condition, so it may not crash. But for me it usually takes only ~10-20 tries to crash with a segfault. I believe the code should use atomic_store_rel_int instead, to get the prop= er memory ordering guarantees. Not just for decimal_point, but for the other fields too. (I haven't looked at other places using the relaxed atomics variants, but there might be more similar bugs there.) In practice, this race condition may be fairly unlikely to hit - the window= is fairly narrow. And it's probably enough for the "main" process to do a sing= le sprintf (which initializes the cache) before starting the threads. Which our tests don't do, but bigger apps probably do. Adding such sprintf call to the reproducer seems to fix it. --=20 You are receiving this mail because: You are the assignee for the bug.=