mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 02:49:02 -04:00
Fix a data race in Windows for the customized strerror()
To proper support multithread we have to use the thread local storage for keeping the latest error.
This commit is contained in:
parent
d927a58e4e
commit
193519d8fc
1 changed files with 28 additions and 10 deletions
|
|
@ -127,8 +127,9 @@ static BOOLEAN (WINAPI* ptr_RtlGenRandom)(PVOID, ULONG);
|
|||
|
||||
/**
|
||||
* Description of the last error.
|
||||
* It's stored in the thread local storage.
|
||||
*/
|
||||
static char* last_error;
|
||||
static pthread_key_t last_error;
|
||||
|
||||
/**
|
||||
* If we are running in Wine.
|
||||
|
|
@ -184,6 +185,12 @@ void os_init(int opt)
|
|||
|
||||
is_scan_winfind = opt != 0;
|
||||
|
||||
/* initialize the thread local storage for strerror(), using free() as desctructor */
|
||||
if (pthread_key_create(&last_error, free) != 0) {
|
||||
log_fatal("Error calling pthread_key_create().\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ntdll = GetModuleHandle("NTDLL.DLL");
|
||||
if (!ntdll) {
|
||||
log_fatal("Error loading the NTDLL module.\n");
|
||||
|
|
@ -223,13 +230,12 @@ void os_init(int opt)
|
|||
}
|
||||
|
||||
exedir_init();
|
||||
|
||||
last_error = 0;
|
||||
}
|
||||
|
||||
void os_done(void)
|
||||
{
|
||||
free(last_error);
|
||||
/* delete the thread local storage for strerror() */
|
||||
pthread_key_delete(last_error);
|
||||
|
||||
/* restore the normal execution level */
|
||||
SetThreadExecutionState(WIN32_ES_CONTINUOUS);
|
||||
|
|
@ -1608,25 +1614,37 @@ int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, u
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* ensure to call the real C strerror() */
|
||||
#undef strerror
|
||||
|
||||
const char* windows_strerror(int err)
|
||||
{
|
||||
/* get the normal C error from the specified err */
|
||||
char* error;
|
||||
char* previous;
|
||||
const char* str = strerror(err);
|
||||
size_t len = strlen(str);
|
||||
|
||||
/* adds space for GetLastError() */
|
||||
len += 32;
|
||||
|
||||
/* reallocate */
|
||||
free(last_error);
|
||||
last_error = malloc(len);
|
||||
if (!last_error)
|
||||
/* allocate a new one */
|
||||
error = malloc(len);
|
||||
if (!error)
|
||||
return str;
|
||||
snprintf(error, len, "%s [%d/%u]", str, err, (unsigned)GetLastError());
|
||||
|
||||
snprintf(last_error, len, "%s [%d/%u]", str, err, (unsigned)GetLastError());
|
||||
return last_error;
|
||||
/* get previous one, if any */
|
||||
previous = pthread_getspecific(last_error);
|
||||
|
||||
/* store in the thread local storage */
|
||||
if (pthread_setspecific(last_error, error) != 0) {
|
||||
free(error);
|
||||
return str;
|
||||
}
|
||||
|
||||
free(previous);
|
||||
return error;
|
||||
}
|
||||
|
||||
ssize_t windows_read(int fd, void* buffer, size_t size)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue