ntdll: Simplify detach sequence now that there is no possible race on process exit.

This commit is contained in:
Alexandre Julliard 2013-07-19 12:13:09 +02:00
parent 14f34c15d1
commit 1c11770159
1 changed files with 24 additions and 35 deletions

View File

@ -1163,16 +1163,13 @@ static void attach_implicitly_loaded_dlls( LPVOID reserved )
* process_detach * process_detach
* *
* Send DLL process detach notifications. See the comment about calling * Send DLL process detach notifications. See the comment about calling
* sequence at process_attach. Unless the bForceDetach flag * sequence at process_attach.
* is set, only DLLs with zero refcount are notified.
*/ */
static void process_detach( BOOL bForceDetach, LPVOID lpReserved ) static void process_detach(void)
{ {
PLIST_ENTRY mark, entry; PLIST_ENTRY mark, entry;
PLDR_MODULE mod; PLDR_MODULE mod;
RtlEnterCriticalSection( &loader_section );
if (bForceDetach) process_detaching = 1;
mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList; mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
do do
{ {
@ -1183,21 +1180,19 @@ static void process_detach( BOOL bForceDetach, LPVOID lpReserved )
/* Check whether to detach this DLL */ /* Check whether to detach this DLL */
if ( !(mod->Flags & LDR_PROCESS_ATTACHED) ) if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
continue; continue;
if ( mod->LoadCount && !bForceDetach ) if ( mod->LoadCount && !process_detaching )
continue; continue;
/* Call detach notification */ /* Call detach notification */
mod->Flags &= ~LDR_PROCESS_ATTACHED; mod->Flags &= ~LDR_PROCESS_ATTACHED;
MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr), MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr),
DLL_PROCESS_DETACH, lpReserved ); DLL_PROCESS_DETACH, ULongToPtr(process_detaching) );
/* Restart at head of WINE_MODREF list, as entries might have /* Restart at head of WINE_MODREF list, as entries might have
been added and/or removed while performing the call ... */ been added and/or removed while performing the call ... */
break; break;
} }
} while (entry != mark); } while (entry != mark);
RtlLeaveCriticalSection( &loader_section );
} }
/************************************************************************* /*************************************************************************
@ -1215,7 +1210,6 @@ NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved )
/* don't do any attach calls if process is exiting */ /* don't do any attach calls if process is exiting */
if (process_detaching) return STATUS_SUCCESS; if (process_detaching) return STATUS_SUCCESS;
/* FIXME: there is still a race here */
RtlEnterCriticalSection( &loader_section ); RtlEnterCriticalSection( &loader_section );
@ -2394,7 +2388,8 @@ BOOLEAN WINAPI RtlDllShutdownInProgress(void)
void WINAPI LdrShutdownProcess(void) void WINAPI LdrShutdownProcess(void)
{ {
TRACE("()\n"); TRACE("()\n");
process_detach( TRUE, (LPVOID)1 ); process_detaching = 1;
process_detach();
} }
/****************************************************************** /******************************************************************
@ -2410,7 +2405,6 @@ void WINAPI LdrShutdownThread(void)
/* don't do any detach calls if process is exiting */ /* don't do any detach calls if process is exiting */
if (process_detaching) return; if (process_detaching) return;
/* FIXME: there is still a race here */
RtlEnterCriticalSection( &loader_section ); RtlEnterCriticalSection( &loader_section );
@ -2537,41 +2531,36 @@ static void MODULE_DecRefCount( WINE_MODREF *wm )
*/ */
NTSTATUS WINAPI LdrUnloadDll( HMODULE hModule ) NTSTATUS WINAPI LdrUnloadDll( HMODULE hModule )
{ {
WINE_MODREF *wm;
NTSTATUS retv = STATUS_SUCCESS; NTSTATUS retv = STATUS_SUCCESS;
if (process_detaching) return retv;
TRACE("(%p)\n", hModule); TRACE("(%p)\n", hModule);
RtlEnterCriticalSection( &loader_section ); RtlEnterCriticalSection( &loader_section );
/* if we're stopping the whole process (and forcing the removal of all free_lib_count++;
* DLLs) the library will be freed anyway if ((wm = get_modref( hModule )) != NULL)
*/
if (!process_detaching)
{ {
WINE_MODREF *wm; TRACE("(%s) - START\n", debugstr_w(wm->ldr.BaseDllName.Buffer));
free_lib_count++; /* Recursively decrement reference counts */
if ((wm = get_modref( hModule )) != NULL) MODULE_DecRefCount( wm );
/* Call process detach notifications */
if ( free_lib_count <= 1 )
{ {
TRACE("(%s) - START\n", debugstr_w(wm->ldr.BaseDllName.Buffer)); process_detach();
MODULE_FlushModrefs();
/* Recursively decrement reference counts */
MODULE_DecRefCount( wm );
/* Call process detach notifications */
if ( free_lib_count <= 1 )
{
process_detach( FALSE, NULL );
MODULE_FlushModrefs();
}
TRACE("END\n");
} }
else
retv = STATUS_DLL_NOT_FOUND;
free_lib_count--; TRACE("END\n");
} }
else
retv = STATUS_DLL_NOT_FOUND;
free_lib_count--;
RtlLeaveCriticalSection( &loader_section ); RtlLeaveCriticalSection( &loader_section );