Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WaitForSingleObject with thread handle get stuck while running regsvr32.exe

I have thread A that is creating another thread B, than thread A is waiting using WaitForSingleObject to wait until thread B dies.

The problem is that even though thread B returns from the thread's "thread_func", thread A does not get signaled!.

I know that because I added traces (OutputDebugString) to the end of the thread_func (thread B's main function) and I can see that thread B finishes its execution, but thread A never comes out of the WaitForSingleObject.

Now, I must also add that this code is in a COM object, and the scenario described above is happening when I'm calling regsvr32.exe (it get stuck!), so I believe that thread A is coming from the DLLMain.

Any ideas why thread A does not get signaled ?!?!

like image 458
TCS Avatar asked Dec 03 '22 01:12

TCS


2 Answers

You could be hitting a problem with the loader lock. Windows, has an internal critical section that gets locked whenever a DLL is loaded/unloaded or when thread is started/stopped (DllMain is always called inside that lock). If your waiting thread A has that critical section locked (i.e. you are waiting somewhere from DllMain), while another thread B tries to shutdown and attempts to acquire that loader critical section, you have your deadlock.

To see where the deadlock happens, just run your app from the VS IDE debugger and after it gets stuck, break execution. Then look at all running threads, and note the stack of each one. You should be able to follow each stack and see what each thread is waiting on.

like image 154
DXM Avatar answered Dec 08 '22 00:12

DXM


I think @DXM is right. The documentation on exactly what you can or can't do inside of DllMain is sparse and hard to find, but the bottom line is that you should generally keep it to a bare minimum -- initialize internal variables and such, but that's about it.

The other point I'd make is that you generally should not "call" regsvr32.exe -- ever.

RegSvr32 is basically just a wrapper that loads a DLL into its address space with LoadLibrary, Calls GetProcAddress to get the address of a function named DllRegisterServer, then calls that function. It's much cleaner (and ultimately, easier) to do the job on your own, something like this:

HMODULE mod = LoadLibrary(your_COM_file); 
register_DLL = GetProcAddress(mod, "DllRegisterServer"); 
if ( register_DLL == NULL) { 
        // must not really be a COM object... 
} 

if ( S_OK != register_DLL()) { 
        // registration failed. 
} 
like image 41
Jerry Coffin Avatar answered Dec 08 '22 00:12

Jerry Coffin