aix,ibmi,os390: make uv_exepath thread-safe

Fix thread-safety issue in uv_exepath() for AIX, IBM i, and z/OS platforms
by adding mutex protection around uv__search_path() calls.

The uv__search_path() function calls getenv("PATH") which is not thread-safe.
This fix adds proper mutex synchronization to prevent race conditions when
multiple threads call uv_exepath() concurrently.

Changes:
- aix-common.c: Add mutex protection around uv__search_path call
- os390.c: Add mutex protection and use cached original_exepath when available
- os390-proctitle.c: Make process_title_mutex and related functions non-static,
  add original_exepath variable
- ibmi.c: Add mutex protection around uv__search_path call in uv_setup_args

Fixes #4920
This commit is contained in:
ish1416 2025-11-10 09:41:17 +05:30
parent b33162dd0b
commit 45fe1045e5
4 changed files with 35 additions and 9 deletions

View File

@ -85,5 +85,8 @@ int uv_exepath(char* buffer, size_t* size) {
if (res < 0)
return UV_EINVAL;
return uv__search_path(args, buffer, size);
uv_mutex_lock(&process_title_mutex);
res = uv__search_path(args, buffer, size);
uv_mutex_unlock(&process_title_mutex);
return res;
}

View File

@ -513,12 +513,12 @@ char** uv_setup_args(int argc, char** argv) {
if (argc > 0) {
/* Use argv[0] to determine value for uv_exepath(). */
size = sizeof(exepath);
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
if (uv__search_path(argv[0], exepath, &size) == 0) {
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
original_exepath = uv__strdup(exepath);
uv_mutex_unlock(&process_title_mutex);
}
uv_mutex_unlock(&process_title_mutex);
}
return argv;

View File

@ -25,13 +25,14 @@
#include <stdlib.h>
#include <string.h>
static uv_mutex_t process_title_mutex;
static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
uv_mutex_t process_title_mutex;
uv_once_t process_title_mutex_once = UV_ONCE_INIT;
char* original_exepath = NULL;
static char* process_title = NULL;
static void* args_mem = NULL;
static void init_process_title_mutex_once(void) {
void init_process_title_mutex_once(void) {
uv_mutex_init(&process_title_mutex);
}

View File

@ -152,19 +152,41 @@ static int getexe(char* buf, size_t len) {
* or through some libc APIs. The below approach is to parse the argv[0]'s pattern
* and use it in conjunction with PATH environment variable to craft one.
*/
extern char* original_exepath;
extern uv_mutex_t process_title_mutex;
extern uv_once_t process_title_mutex_once;
extern void init_process_title_mutex_once(void);
int uv_exepath(char* buffer, size_t* size) {
int res;
char args[PATH_MAX];
int pid;
size_t cached_len;
if (buffer == NULL || size == NULL || *size == 0)
return UV_EINVAL;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
if (original_exepath != NULL) {
cached_len = strlen(original_exepath);
*size -= 1;
if (*size > cached_len)
*size = cached_len;
memcpy(buffer, original_exepath, *size);
buffer[*size] = '\0';
uv_mutex_unlock(&process_title_mutex);
return 0;
}
uv_mutex_unlock(&process_title_mutex);
res = getexe(args, sizeof(args));
if (res < 0)
return UV_EINVAL;
return uv__search_path(args, buffer, size);
uv_mutex_lock(&process_title_mutex);
res = uv__search_path(args, buffer, size);
uv_mutex_unlock(&process_title_mutex);
return res;
}