From a0530ce77ea7c448fcf12d67ce528a8f867922e4 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sun, 8 Dec 2019 12:27:31 +0100 Subject: [PATCH] unix: cache address of dlsym("mkostemp") MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Look up the "mkostemp" symbol once instead of on every call to uv_fs_mkstemp(). PR-URL: https://github.com/libuv/libuv/pull/2564 Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: Richard Lau Reviewed-By: Santiago Gimeno Reviewed-By: Saúl Ibarra Corretgé --- src/unix/fs.c | 54 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/src/unix/fs.c b/src/unix/fs.c index a864ffd8..07df52a6 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -259,10 +259,29 @@ static ssize_t uv__fs_mkdtemp(uv_fs_t* req) { } +static int (*uv__mkostemp)(char*, int); + + +static void uv__mkostemp_initonce(void) { + /* z/os doesn't have RTLD_DEFAULT but that's okay + * because it doesn't have mkostemp(O_CLOEXEC) either. + */ +#ifdef RTLD_DEFAULT + uv__mkostemp = (int (*)(char*, int)) dlsym(RTLD_DEFAULT, "mkostemp"); + + /* We don't care about errors, but we do want to clean them up. + * If there has been no error, then dlerror() will just return + * NULL. + */ + dlerror(); +#endif /* RTLD_DEFAULT */ +} + + static int uv__fs_mkstemp(uv_fs_t* req) { + static uv_once_t once = UV_ONCE_INIT; int r; #ifdef O_CLOEXEC - int (*mkostemp_function)(char*, int); static int no_cloexec_support; #endif static const char pattern[] = "XXXXXX"; @@ -284,30 +303,23 @@ static int uv__fs_mkstemp(uv_fs_t* req) { return -1; } + uv_once(&once, uv__mkostemp_initonce); + #ifdef O_CLOEXEC - if (no_cloexec_support == 0) { - mkostemp_function = (int (*)(char*, int)) dlsym(RTLD_DEFAULT, "mkostemp"); + if (no_cloexec_support == 0 && uv__mkostemp != NULL) { + r = uv__mkostemp(path, O_CLOEXEC); - /* We don't care about errors, but we do want to clean them up. - If there has been no error, then dlerror() will just return - NULL. */ - dlerror(); + if (r >= 0) + return r; - if (mkostemp_function != NULL) { - r = mkostemp_function(path, O_CLOEXEC); + /* If mkostemp() returns EINVAL, it means the kernel doesn't + support O_CLOEXEC, so we just fallback to mkstemp() below. */ + if (errno != EINVAL) + return r; - if (r >= 0) - return r; - - /* If mkostemp() returns EINVAL, it means the kernel doesn't - support O_CLOEXEC, so we just fallback to mkstemp() below. */ - if (errno != EINVAL) - return r; - - /* We set the static variable so that next calls don't even - try to use mkostemp. */ - no_cloexec_support = 1; - } + /* We set the static variable so that next calls don't even + try to use mkostemp. */ + no_cloexec_support = 1; } #endif /* O_CLOEXEC */