The DllMain() help in the PSDK has the following
tidbit:
While it is acceptable to create synchronization
objects in
DllMain, you should not perform synchronization in DllMain (or
a function called by DllMain) because all calls to DllMain
are serialized. Waiting on synchronization objects in DllMain
can cause a deadlock.
Does ReactOS serialize calls to DllMain? I would think if it
was, CreateRemoteThread() would block waiting for
DLL_THREAD_ATTACH until DLL_PROCESS_DETACH had finished.
(And then of course, there are other issues to be dealt
with because the DLL is unloaded.)
ExitProcess() PSDK has the following tidbit which might
also help:
The ExitProcess, ExitThread, CreateThread,
CreateRemoteThread
functions, and a process that is starting (as the result of a
call by CreateProcess) are serialized between each other
within a process. Only one of these events can happen in an
address space at a time. This means the following restrictions
hold:
During process startup and DLL initialization routines, new
threads can be created, but they do not begin execution until
DLL initialization is done for the process. Only one thread in
a process can be in a DLL initialization or detach routine at
a time. If any process is in its DLL initialization or detach
routine, ExitProcess does not return.
Hope this helps.
Thanks,
Joseph
Ge van Geldorp wrote:
While working on proper logoff/shutdown processing,
I'm
running into an interesting race condition inside kernel32.
The shutdown command (apps/utils/shutdown) calls
ExitWindowsEx() and then terminates, which causes kernel32's
DllMain() function to be called with the DLL_PROCESS_DETACH
reason. This will clean up kernel32 resources, like calling
RtlDeleteCriticalSection(&ConsoleLock).
Now, before the process is completely shutdown, CSRSS will
send it a CTRL_LOGOFF_EVENT. To deliver this event, CSRSS
calls CreateRemoteThread(). So CreateRemoteThread() is called
while the main thread is executing DLL_PROCESS_DETACH cleanup.
During handling of CTRL_LOGOFF_EVENT, the new thread will try
to enter the ConsoleLock critical section, which was already
deleted by the main thread. Chaos results.
To solve this, first I was looking for a way to disable new
thread creation when a process enters ExitProcess(), but that
won't solve the problem. We can still have a thread A which
calls ExitProcess(), have a context switch to existing thread
B of the same process which does something that needs the
ConsoleLock. Then I considered SuspendThread()ing all other
threads of the process when ExitProcess() is called, but that
could potentially lead to deadlocks if the suspended threads
hold synchronization objects. So now I'm inclined to believe
that the solution is to just not do the resource cleanup
during DLL_PROCESS_DETACH handling. But that doesn't feel very
clean either. Anyone have a better idea?
GvG
_______________________________________________ Ros-dev
mailing list Ros-dev(a)reactos.org
http://www.reactos.org/mailman/listinfo/ros-dev