I have a multithreaded application running on WIN32 which uses a semaphore to protect a linked-list. Very occasionally this locks-up. When it locks-up I can stop the application in cppvsdbg
under Visual Studio Code and I can see that two of the threads are waiting on the semaphore, i.e. they are blocked at:
WaitForSingleObject(handle, INFINITE);
However, the third thread is blocked here:
ReleaseSemaphore(handle, 1, NULL);
...i.e. it seems to have blocked on ReleaseSemaphore()
, the very function which of course would allow one of the other two threads to run. If I single step in the debugger, or I set a break-point just beyond the ReleaseSemaphore()
call and continue running, nothing budges, the application remains locked up. The thread that is blocked at ReleaseSemaphore()
is running at priority 0, the other two threads at priorities 0 and -1, so I can't see how thread priority could cause an issue.
More than that, I don't understand why ReleaseSemaphore()
would block under any circumstances. The value of handle
is 0x000000ec, which is what it was at the start of the day, so the value of handle
hasn't been corrupted, though I guess it is possible that the contents of handle
might have been messed up somehow...? Not sure how I would debug that.
Does anyone have any suggestions as to why ReleaseSemaphore()
might lock, or what additional things I might poke at in the debugger when the problem occurs to determine what's up?
EDIT: the code is compiled with /Od
to avoid any misalignment between the visual debug and the code, this is a screen-shot of what the cppvsdbg
window shows for the thread which appears to be blocked on ReleaseSemaphore()
:
CodePudding user response:
And the correct answer is: no, the Win32 API function ReleaseSemaphore()
can never block.
The reason it appeared to be blocking in this case was because, separately, we needed to simulate critical sections on Windows (recalling that this code usually runs in an embedded system on an RTOS, Windows is only for rapid development). To simulate a critical section on Windows we call SuspendThread()
(and later ResumeThread()
) on all threads except the current thread. A failure was occurring elsewhere in the code while such a simulated critical section was in place, and it so happened that this coincided with the ReleaseSemaphore()
call most of the time, making it look as though ReleaseSemaphore()
had blocked; it hadn't, the thread just happened to get suspended there.
So we just had to fix the other bug and this apparent problem went away.