From 0b170bae41b2dcd5eeabc09628ce0f3cc5817e6f Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 9 Nov 2023 15:56:32 +0100 Subject: [PATCH] random: Fix multithread-safety bug. * m4/random.m4 (gl_FUNC_RANDOM): Override on macOS, FreeBSD, Solaris, Cygwin, Haiku. * lib/random.c: Include glthread/lock.h. (__libc_lock_define_initialized, __libc_lock_lock, __libc_lock_unlock): Define to do real locking. * modules/random (Depends-on): Add lock. * doc/posix-functions/random.texi: Mention the multithread-safety problem. --- ChangeLog | 12 ++++++++++++ doc/posix-functions/random.texi | 3 ++- lib/random.c | 8 ++++---- m4/random.m4 | 11 +++++++++-- modules/random | 3 ++- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 83db185ad8..396668b66c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2023-11-10 Bruno Haible + + random: Fix multithread-safety bug. + * m4/random.m4 (gl_FUNC_RANDOM): Override on macOS, FreeBSD, Solaris, + Cygwin, Haiku. + * lib/random.c: Include glthread/lock.h. + (__libc_lock_define_initialized, __libc_lock_lock, __libc_lock_unlock): + Define to do real locking. + * modules/random (Depends-on): Add lock. + * doc/posix-functions/random.texi: Mention the multithread-safety + problem. + 2023-11-08 Bruno Haible pthread-rwlock: Port to Mac OS X 10.4. diff --git a/doc/posix-functions/random.texi b/doc/posix-functions/random.texi index 19349617be..84cacbe8b5 100644 --- a/doc/posix-functions/random.texi +++ b/doc/posix-functions/random.texi @@ -15,7 +15,8 @@ mingw, MSVC 14. This function is only defined as an inline function on some platforms: Android 4.4. @item - +This function is not multithread-safe on some platforms: +macOS 12.5, FreeBSD 13.2, Solaris 11.4, Cygwin 3.4.6, Haiku. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/random.c b/lib/random.c index 50080ef2d5..ac5999101a 100644 --- a/lib/random.c +++ b/lib/random.c @@ -67,10 +67,10 @@ #ifdef _LIBC # include #else -/* Allow memory races; that's random enough. */ -# define __libc_lock_define_initialized(class, name) -# define __libc_lock_lock(name) ((void) 0) -# define __libc_lock_unlock(name) ((void) 0) +# include "glthread/lock.h" +# define __libc_lock_define_initialized gl_lock_define_initialized +# define __libc_lock_lock gl_lock_lock +# define __libc_lock_unlock gl_lock_unlock #endif /* An improved random number generation package. In addition to the standard diff --git a/m4/random.m4 b/m4/random.m4 index 939a844029..5a2db0c157 100644 --- a/m4/random.m4 +++ b/m4/random.m4 @@ -1,4 +1,4 @@ -# random.m4 serial 4 +# random.m4 serial 4.1 dnl Copyright (C) 2012-2023 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -7,6 +7,7 @@ dnl with or without modifications, as long as this notice is preserved. AC_DEFUN([gl_FUNC_RANDOM], [ AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl We can't use AC_CHECK_FUNC here, because random() is defined as a dnl static inline function when compiling for Android 4.4 or older. @@ -31,7 +32,13 @@ AC_DEFUN([gl_FUNC_RANDOM], if test $ac_cv_func_setstate = no; then HAVE_SETSTATE=0 fi - if test $ac_cv_func_initstate = no || test $ac_cv_func_setstate = no; then + dnl On several platforms, random() is not multithread-safe. + if test $ac_cv_func_initstate = no || test $ac_cv_func_setstate = no \ + || case "$host_os" in \ + darwin* | freebsd* | solaris* | cygwin* | haiku*) true ;; \ + *) false ;; \ + esac + then dnl In order to define initstate or setstate, we need to define all the dnl functions at once. REPLACE_RANDOM=1 diff --git a/modules/random b/modules/random index a6ccbb777d..9774088bda 100644 --- a/modules/random +++ b/modules/random @@ -6,8 +6,9 @@ lib/random.c m4/random.m4 Depends-on: -libc-config [test $HAVE_RANDOM = 0 || test $REPLACE_RANDOM = 1 || test $REPLACE_INITSTATE = 1 || test $REPLACE_SETSTATE = 1] stdlib +libc-config [test $HAVE_RANDOM = 0 || test $REPLACE_RANDOM = 1 || test $REPLACE_INITSTATE = 1 || test $REPLACE_SETSTATE = 1] +lock [test $HAVE_RANDOM = 0 || test $REPLACE_RANDOM = 1 || test $REPLACE_INITSTATE = 1 || test $REPLACE_SETSTATE = 1] stdint [test $HAVE_RANDOM = 0 || test $REPLACE_RANDOM = 1 || test $REPLACE_INITSTATE = 1 || test $REPLACE_SETSTATE = 1] random_r [test $HAVE_RANDOM = 0 || test $REPLACE_RANDOM = 1 || test $REPLACE_INITSTATE = 1 || test $REPLACE_SETSTATE = 1] -- 2.39.5