From 7c4a774e4eb9dfdf9271b6bbef2bb1b5191db398 Mon Sep 17 00:00:00 2001 From: David Fort Date: Fri, 3 Mar 2023 15:45:15 +0100 Subject: [PATCH] winpr: fix WaitForMultipleObjectsEx(alertable) call from non winpr threads When WaitForMultipleObjectsEx is called with the alertable flag set from a non WinPR thread, we shall not try to treat APC, as for sure there is no APC scheduled, as previous call that would have scheduled such APC would have failed. --- winpr/libwinpr/synch/sleep.c | 14 ++++++------ winpr/libwinpr/synch/wait.c | 41 +++++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/winpr/libwinpr/synch/sleep.c b/winpr/libwinpr/synch/sleep.c index 95e9eed51..14950884a 100644 --- a/winpr/libwinpr/synch/sleep.c +++ b/winpr/libwinpr/synch/sleep.c @@ -63,15 +63,17 @@ DWORD SleepEx(DWORD dwMilliseconds, BOOL bAlertable) DWORD ret = WAIT_FAILED; BOOL autoSignalled; - if (!thread) + if (thread) { - WLog_ERR(TAG, "unable to retrieve currentThread"); - return WAIT_FAILED; + /* treat re-entrancy if a completion is calling us */ + if (thread->apc.treatingCompletions) + bAlertable = FALSE; } - - /* treat re-entrancy if a completion is calling us */ - if (thread->apc.treatingCompletions) + else + { + /* called from a non WinPR thread */ bAlertable = FALSE; + } if (!bAlertable || !thread->apc.length) { diff --git a/winpr/libwinpr/synch/wait.c b/winpr/libwinpr/synch/wait.c index 8c442a50d..66a06f992 100644 --- a/winpr/libwinpr/synch/wait.c +++ b/winpr/libwinpr/synch/wait.c @@ -263,18 +263,20 @@ DWORD WaitForSingleObjectEx(HANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertabl if (bAlertable) { thread = (WINPR_THREAD*)_GetCurrentThread(); - if (!thread) + if (thread) { - WLog_ERR(TAG, "failed to retrieve currentThread"); - return WAIT_FAILED; + /* treat reentrancy, we can't switch to alertable state when we're already + treating completions */ + if (thread->apc.treatingCompletions) + bAlertable = FALSE; + else + extraFds = thread->apc.length; } - - /* treat reentrancy, we can't switch to alertable state when we're already - treating completions */ - if (thread->apc.treatingCompletions) - bAlertable = FALSE; else - extraFds = thread->apc.length; + { + /* called from a non WinPR thread */ + bAlertable = FALSE; + } } int fd = winpr_Handle_getFd(Object); @@ -365,15 +367,20 @@ DWORD WaitForMultipleObjectsEx(DWORD nCount, const HANDLE* lpHandles, BOOL bWait if (bAlertable) { thread = winpr_GetCurrentThread(); - if (!thread) - return WAIT_FAILED; - - /* treat reentrancy, we can't switch to alertable state when we're already - treating completions */ - if (thread->apc.treatingCompletions) - bAlertable = FALSE; + if (thread) + { + /* treat reentrancy, we can't switch to alertable state when we're already + treating completions */ + if (thread->apc.treatingCompletions) + bAlertable = FALSE; + else + extraFds = thread->apc.length; + } else - extraFds = thread->apc.length; + { + /* most probably we're not called from WinPR thread, so we can't have any APC */ + bAlertable = FALSE; + } } if (!pollset_init(&pollset, nCount + extraFds))