Windows: Under what circumstances cannot SetEvent () return immediately?

I have a thread that, when its function exits its loop (the exit is triggered by an event), it does some cleanup and then sets another event to let the master thread know it's done.

However, under some circumstances, SetEvent () does not seem to return after it sets the "I did" event.

This thread is part of the DLL and the problem seems to occur after loading / attaching the DLL, starting the thread, ending the thread, and deleting / unloading the DLL multiple times without shutting down the application in between. The number of times this sequence is repeated before this problem is variable.

If you are skeptical that I know what I am talking about, I figured out what was happening by copying the SetEvent () call with the OutputDebugString () calls. Output appears before SetEvent (). The waiting thread then produces output that indicates that the event is set.

However, the second call to OutputDebugString () on the output stream (one of AFTER's SetEvent ()) never occurs, or at least its string never appears. If this happens, the app will crash after a few seconds.

(Note that the calls to OutputDebugString () were added after the problem occurred, so it is unlikely to hang in there and not in SetEvent ().)

I'm not entirely sure what is causing the crash, but it occurs on the same thread where SetEvent () did not return immediately (I tracked / dumped thread IDs). I suppose it's possible that SetEvent () finally returns, to which point the context it returns to is gone / invalid, but what could be causing such a delay?

It turns out I was blinded, looking at this code for so long, and it never even occurred to me to check the return code. I am still looking at this for today, so I will know that he will return (if he does) on Monday, and then I will edit this question with this information.

Update: I changed the (main) code to wait for the thread to exit, not to set it, and removed the call to SetEvent () from the sub thread. This changed the nature of the error: now instead of not returning from SetEvent (), it does not exit the thread at all, and it all hangs.

This indicates that the problem is not with SetEvent (), but with something deeper. Don't know what else, but it's good not to chase that dead end.

Update (13.02.09):
It turned out that the problem was deeper than I thought when I asked this question. jdigital (and possibly others) pretty much nailed down the main issue: we were trying to unload the thread as part of the DLL detach process.

This, as I did not understand then, but have since learned that here and elsewhere (for example, Raymond Chen's blog), this is a very bad thing.

The problem was that due to how it was encoded and how it behaved, it is not clear what the underlying problem was - it was disguised as all sorts of other Bad Behaviors I had to wade through.

Some of the suggestions here helped me do this, so I am grateful to everyone who contributed. Thank!

+1


source to share


4 answers


Who is unloading the DLL and at what time is the unloading performed? I'm wondering if there is a sync issue here where the DLL is unloaded before the thread finishes.



+1


source


Are you crossing HANDLE *

on SetEvent

? Most likely the event descriptor reference is invalid and the failure is an access violation (i.e. garbage access).



+2


source


You might want to use WinDbg for crash detection and stack inspection.

0


source


Why would you need to set an event on a slave thread to start the main thread that the thread is executing? just exit the thread, the main calling thread has to wait for the worker thread to exit, like the pseudo code -

Master
{
   TerminateEvent = CreateEvent ( ... ) ;
   ThreadHandle = BeginThread ( Slave, (LPVOID) TerminateEvent ) ;
   ...
   Do some work
   ...
   SetEvent ( TerminateEvent ) ;
   WaitForSingleObject ( ThreadHandle, SOME_TIME_OUT ) ;
   CloseHandle ( TerminateEvent ) ;
   CloseHandle ( ThreadHandle ) ; 
}

Slave ( LPVOID ThreadParam )
{
   TerminateEvent = (HANDLE) ThreadParam ;
   while ( WaitForSingleObject ( TerminateEvent, SOME__SHORT_TIME_OUT ) == WAIT_TIMEOUT )
   { 
      ... 
      Do some work 
      ...
   }
}

      

There are many error conditions and states to check, but this is the essence of how I usually do it.

If you can get it, get this book, it changed my life regarding Windows development when I first read it many years ago.

Windows Advanced Features: Developer's Guide for Win32 Api for Windows Nt 3.5 and Windows 95 (paperback) by Jeffrey Richter (author)

0


source







All Articles