unix: cache address of dlsym("mkostemp")

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 <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
Ben Noordhuis 2019-12-08 12:27:31 +01:00
parent 0d3b487f5d
commit a0530ce77e

View File

@ -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 */