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 <behlendorf1@llnl.gov>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Signed-off-by: Richard Kojedzinszky <richard@kojedz.in>
Closes #15793
Closes #16640
Closes #16923
This commit is contained in:
Richard Kojedzinszky 2025-01-04 19:33:27 +01:00 committed by GitHub
parent 939e0237c5
commit dc0324bfa9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 10 additions and 7 deletions

View File

@ -33,7 +33,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER], [
ZFS_AC_CONFIG_USER_MAKEDEV_IN_MKDEV
ZFS_AC_CONFIG_USER_ZFSEXEC
AC_CHECK_FUNCS([execvpe issetugid mlockall strerror_l strlcat strlcpy gettid])
AC_CHECK_FUNCS([execvpe issetugid mlockall strlcat strlcpy gettid])
AC_SUBST(RM)
])

View File

@ -27,7 +27,7 @@
#define _LIBZUTIL_H extern __attribute__((visibility("default")))
#include <string.h>
#include <locale.h>
#include <pthread.h>
#include <sys/nvpair.h>
#include <sys/fs/zfs.h>
@ -276,11 +276,14 @@ _LIBZUTIL_H void update_vdev_config_dev_sysfs_path(nvlist_t *nv,
* Thread-safe strerror() for use in ZFS libraries
*/
static inline char *zfs_strerror(int errnum) {
#ifdef HAVE_STRERROR_L
return (strerror_l(errnum, uselocale(0)));
#else
return (strerror(errnum));
#endif
static __thread char errbuf[512];
static pthread_mutex_t zfs_strerror_lock = PTHREAD_MUTEX_INITIALIZER;
(void) pthread_mutex_lock(&zfs_strerror_lock);
(void) strlcpy(errbuf, strerror(errnum), sizeof (errbuf));
(void) pthread_mutex_unlock(&zfs_strerror_lock);
return (errbuf);
}
#ifdef __cplusplus