Date: Tue, 30 Jun 2026 16:59:38 +0000 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 Message-ID: <bug-296410-13406@https.bugs.freebsd.org/bugzilla/>
index | next in thread | raw e-mail
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=296410 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 segfaults in tests using threads. This seems to affect only the AArch64 machine (which 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=fp@entry=0x889dab00, locale=locale@entry=0x841dfcf0 <__xlocale_global_locale>, serrno=0, fmt0=fmt0@entry=0x20087a "Connection: %d", ap=...) at /usr/src/lib/libc/stdio/vfprintf.c:477 warning: 477 /usr/src/lib/libc/stdio/vfprintf.c: No such file or directory [Current thread is 1 (LWP 933707)] (gdb) bt #0 __vfprintf (fp=fp@entry=0x889dab00, locale=locale@entry=0x841dfcf0 <__xlocale_global_locale>, serrno=0, fmt0=fmt0@entry=0x20087a "Connection: %d", ap=...) at /usr/src/lib/libc/stdio/vfprintf.c:477 #1 0x000000008411d434 in vsprintf_l (locale=0x841dfcf0 <__xlocale_global_locale>, ap=..., str=<optimized out>, fmt=<optimized out>) at /usr/src/lib/libc/stdio/vsprintf.c:61 #2 vsprintf (str=0x889daefc "", fmt=<optimized out>, ap=...) at /usr/src/lib/libc/stdio/vsprintf.c:68 #3 0x00000000841123f4 in sprintf (str=0x0, str@entry=0x889daefc "", fmt=0x841dfcf0 <__xlocale_global_locale> "") at /usr/src/lib/libc/stdio/sprintf.c:56 #4 0x0000000000210ed8 in fn (arg=0x0) at prep.pgc:39 #5 0x00000000847844fc in thread_start (curthread=0x63044546d010) 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 = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point)); After investigating a bit, I believe this is due to localeconv_l using atomics in relaxed mode when updating the decimal_point: if (atomic_load_acq_int(&loc->numeric_locale_changed) != 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, without seeing the updated decimal_point pointer. Which leads to the crash. This can be reproduced by a simple program: ------ #include <stdio.h> #include <pthread.h> void *fn(void *arg) { char buf[128]; for(int i=0; i<10000; i++) sprintf(buf, "%d", 1); return NULL; } int main() { pthread_t th[100]; for(int i=0; i<100; i++) pthread_create(&th[i], NULL, fn, NULL); for(int i=0; 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 proper 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 single 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. -- You are receiving this mail because: You are the assignee for the bug.home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-296410-13406>
