From e9da224bce287653f96235bd6ae02da6f8f8b219 Mon Sep 17 00:00:00 2001 From: Niklas Hambüchen Date: Fri, 17 May 2019 02:50:03 +0200 Subject: Allow disabling random_r() usage manually. See #279. This allows building hmatrix against the musl libc, which allows easily linking Haskell programs statically. A feature-detection for random_r() would be even better, but this will do for now. --- packages/base/hmatrix.cabal | 8 ++++++++ packages/base/src/Internal/C/vector-aux.c | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/base/hmatrix.cabal b/packages/base/hmatrix.cabal index 1380a36..c371ae7 100644 --- a/packages/base/hmatrix.cabal +++ b/packages/base/hmatrix.cabal @@ -36,6 +36,11 @@ flag disable-default-paths default: False manual: True +flag no-random_r + description: When enabled, don't depend on the random_r() C function. + default: False + manual: True + library Build-Depends: base >= 4.8 && < 5, @@ -99,6 +104,9 @@ library cc-options: -msse2 + if flag(no-random_r) + cc-options: -DNO_RANDOM_R + if os(OSX) if flag(openblas) if !flag(disable-default-paths) diff --git a/packages/base/src/Internal/C/vector-aux.c b/packages/base/src/Internal/C/vector-aux.c index dcd6c0b..08dc835 100644 --- a/packages/base/src/Internal/C/vector-aux.c +++ b/packages/base/src/Internal/C/vector-aux.c @@ -932,20 +932,20 @@ int vectorScan(char * file, int* n, double**pp){ //////////////////////////////////////////////////////////////////////////////// -#if defined (__APPLE__) || (__FreeBSD__) +#if defined (__APPLE__) || (__FreeBSD__) || defined(NO_RANDOM_R) /* FreeBSD and Mac OS X do not provide random_r(), thread safety cannot be guaranteed. For FreeBSD and Mac OS X, nrand48() is much better than random(). See: http://www.evanjones.ca/random-thread-safe.html */ -#pragma message "randomVector is not thread-safe in OSX and FreeBSD" +#pragma message "randomVector is not thread-safe in OSX and FreeBSD or with NO_RANDOM_R" #endif -#if defined (__APPLE__) || (__FreeBSD__) || defined(_WIN32) || defined(WIN32) +#if defined (__APPLE__) || (__FreeBSD__) || defined(NO_RANDOM_R) || defined(_WIN32) || defined(WIN32) /* Windows use thread-safe random See: http://stackoverflow.com/questions/143108/is-windows-rand-s-thread-safe */ -#if defined (__APPLE__) || (__FreeBSD__) +#if defined (__APPLE__) || (__FreeBSD__) || defined(NO_RANDOM_R) inline double urandom() { /* the probalility of matching will be theoretically p^3(in fact, it is not) -- cgit v1.2.3 From e6914acb75514fbb2bd2e736c4157e38abdb1ec0 Mon Sep 17 00:00:00 2001 From: Niklas Hambüchen Date: Sun, 30 Jun 2019 14:27:20 +0200 Subject: urandom(): Refactor CPP, clarify warnings. See #279. * 2 identical CPP #ifdef sections were merged for easier readibility. * Warnings and comments now include more concrete explanations on in which situations urandom() isn't thread-safe and what not being thread-safe means in that case. * Added TODO on how the situation can be fixed long-term. --- packages/base/src/Internal/C/vector-aux.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/packages/base/src/Internal/C/vector-aux.c b/packages/base/src/Internal/C/vector-aux.c index 08dc835..73455a5 100644 --- a/packages/base/src/Internal/C/vector-aux.c +++ b/packages/base/src/Internal/C/vector-aux.c @@ -932,21 +932,34 @@ int vectorScan(char * file, int* n, double**pp){ //////////////////////////////////////////////////////////////////////////////// -#if defined (__APPLE__) || (__FreeBSD__) || defined(NO_RANDOM_R) -/* FreeBSD and Mac OS X do not provide random_r(), thread safety cannot be - guaranteed. - For FreeBSD and Mac OS X, nrand48() is much better than random(). - See: http://www.evanjones.ca/random-thread-safe.html -*/ -#pragma message "randomVector is not thread-safe in OSX and FreeBSD or with NO_RANDOM_R" -#endif - #if defined (__APPLE__) || (__FreeBSD__) || defined(NO_RANDOM_R) || defined(_WIN32) || defined(WIN32) /* Windows use thread-safe random See: http://stackoverflow.com/questions/143108/is-windows-rand-s-thread-safe */ #if defined (__APPLE__) || (__FreeBSD__) || defined(NO_RANDOM_R) +/* For FreeBSD, Mac OS X, and other libcs (like `musl`) that do not provide + random_r(), or if the use of random_r() is explicitly disabled, thread safety + cannot be guaranteed. + As per current understanding, this should at worst lead to less "random" + numbers being generated, in particular + * if another thread somebody calls lcong48() at the same time as nrand48() + is called + * in addition to that, for glibc with NO_RANDOM_R enabled when ndrand48() + is called for the first time by multiple threads in parallel due to the + initialisation function placed within it + See: http://www.evanjones.ca/random-thread-safe.html + + For FreeBSD and Mac OS X, nrand48() is much better than random(). + See: http://www.evanjones.ca/random-thread-safe.html + + TODO: As mentioned in the linked article, this could be fixed: + "the best solution for truly portable applications is to include + your own random number generator implementation, + and not rely on the system's C library". +*/ +#pragma message "randomVector is not thread-safe in OSX and FreeBSD or with NO_RANDOM_R; this likely leads to less random numbers at worst; see http://www.evanjones.ca/random-thread-safe.html" + inline double urandom() { /* the probalility of matching will be theoretically p^3(in fact, it is not) p is matching probalility of random(). -- cgit v1.2.3