Skip to content

Commit dc0324b

Browse files
fix: make zfs_strerror really thread-safe and portable
#15793 wanted to make zfs_strerror threadsafe, unfortunately, it turned out that strerror_l() usage was wrong, and also, some libc implementations dont have strerror_l(). zfs_strerror() now simply calls original strerror() and copies the result to a thread-local buffer, then returns that. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Signed-off-by: Richard Kojedzinszky <[email protected]> Closes #15793 Closes #16640 Closes #16923
1 parent 939e023 commit dc0324b

File tree

2 files changed

+10
-7
lines changed

2 files changed

+10
-7
lines changed

config/user.m4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER], [
3333
ZFS_AC_CONFIG_USER_MAKEDEV_IN_MKDEV
3434
ZFS_AC_CONFIG_USER_ZFSEXEC
3535
36-
AC_CHECK_FUNCS([execvpe issetugid mlockall strerror_l strlcat strlcpy gettid])
36+
AC_CHECK_FUNCS([execvpe issetugid mlockall strlcat strlcpy gettid])
3737
3838
AC_SUBST(RM)
3939
])

include/libzutil.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
#define _LIBZUTIL_H extern __attribute__((visibility("default")))
2828

2929
#include <string.h>
30-
#include <locale.h>
30+
#include <pthread.h>
3131
#include <sys/nvpair.h>
3232
#include <sys/fs/zfs.h>
3333

@@ -276,11 +276,14 @@ _LIBZUTIL_H void update_vdev_config_dev_sysfs_path(nvlist_t *nv,
276276
* Thread-safe strerror() for use in ZFS libraries
277277
*/
278278
static inline char *zfs_strerror(int errnum) {
279-
#ifdef HAVE_STRERROR_L
280-
return (strerror_l(errnum, uselocale(0)));
281-
#else
282-
return (strerror(errnum));
283-
#endif
279+
static __thread char errbuf[512];
280+
static pthread_mutex_t zfs_strerror_lock = PTHREAD_MUTEX_INITIALIZER;
281+
282+
(void) pthread_mutex_lock(&zfs_strerror_lock);
283+
(void) strlcpy(errbuf, strerror(errnum), sizeof (errbuf));
284+
(void) pthread_mutex_unlock(&zfs_strerror_lock);
285+
286+
return (errbuf);
284287
}
285288

286289
#ifdef __cplusplus

0 commit comments

Comments
 (0)