diff options
author | SChernykh <sergey.v.chernykh@gmail.com> | 2023-03-29 08:43:47 +0200 |
---|---|---|
committer | SChernykh <sergey.v.chernykh@gmail.com> | 2023-03-29 08:44:20 +0200 |
commit | c742fa4c6ef83eb7f2495128a23d7cc250dc7db2 (patch) | |
tree | 2f674a5dbd1aa073e9e0b9b463e360c2c808f615 /src/crypto/c_threads.h | |
parent | Merge pull request #8801 (diff) | |
download | monero-c742fa4c6ef83eb7f2495128a23d7cc250dc7db2.tar.xz |
Fixed deadlock and crash when syncing with full dataset on Windows
It's not allowed to use WaitForSingleObject with _beginthread, because the thread closes its own handle before exiting.
So the wait function will either wait on an invalid handle, or on a different handle used by something else.
Or, if it starts waiting before the thread exits, the behavior is undefined according to MS: "If this handle is closed while the wait is still pending, the function's behavior is undefined."
In my test sync I observed threads getting stuck infinitely on WaitForSingleObject, and then rx_set_main_seedhash spamming new threads when RandomX seed changes again. Eventually the system ran out of resources, and monerod aborted with "Couldn't start RandomX seed thread" message.
This PR fixes it by using `_beginthreadex` instead and explicitly closing the handle when it's safe.
Diffstat (limited to 'src/crypto/c_threads.h')
-rw-r--r-- | src/crypto/c_threads.h | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/src/crypto/c_threads.h b/src/crypto/c_threads.h index b4f773641..3457738b3 100644 --- a/src/crypto/c_threads.h +++ b/src/crypto/c_threads.h @@ -42,10 +42,11 @@ #define CTHR_RWLOCK_TRYLOCK_READ(x) TryAcquireSRWLockShared(&x) #define CTHR_THREAD_TYPE HANDLE -#define CTHR_THREAD_RTYPE void -#define CTHR_THREAD_RETURN return -#define CTHR_THREAD_CREATE(thr, func, arg) ((thr = (HANDLE)_beginthread(func, 0, arg)) != -1L) -#define CTHR_THREAD_JOIN(thr) WaitForSingleObject((HANDLE)thr, INFINITE) +#define CTHR_THREAD_RTYPE unsigned __stdcall +#define CTHR_THREAD_RETURN _endthreadex(0); return 0; +#define CTHR_THREAD_CREATE(thr, func, arg) ((thr = (HANDLE)_beginthreadex(0, 0, func, arg, 0, 0)) != 0L) +#define CTHR_THREAD_JOIN(thr) do { WaitForSingleObject(thr, INFINITE); CloseHandle(thr); } while(0) +#define CTHR_THREAD_CLOSE(thr) CloseHandle((HANDLE)thr); #else @@ -64,5 +65,6 @@ #define CTHR_THREAD_RETURN return NULL #define CTHR_THREAD_CREATE(thr, func, arg) (pthread_create(&thr, NULL, func, arg) == 0) #define CTHR_THREAD_JOIN(thr) pthread_join(thr, NULL) +#define CTHR_THREAD_CLOSE(thr) #endif |