Skip to content

Commit 5b402c2

Browse files
committed
fix: make zfs_strerror really thread-safe and portable
openzfs#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 openzfs#15793 Closes openzfs#16640 Closes openzfs#16923
1 parent 28b7c7f commit 5b402c2

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

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

284287
#ifdef __cplusplus

0 commit comments

Comments
 (0)