ntdll: Fixed LdrUnloadDll may recursion unload same dll
Sebastian Lackner
sebastian at fds-team.de
Fri Feb 10 11:43:00 CST 2017
On 09.02.2017 10:39, 谢威 wrote:
> From 3b5efb522f3ef46b009e6a159a605e087e8841a9 Mon Sep 17 00:00:00 2001
> From: Wei xie <xiewei at linuxdeepin.com>
> Date: Thu, 19 Jan 2017 14:55:44 +0800
> Subject: [PATCH] ntdll: Fixed LdrUnloadDll may recursion unload same dll
>
> Signed-off-by: Wei xie <xiewei at linuxdeepin.com>
> ---
> dlls/ntdll/loader.c | 20 +++++++++++++++-----
> 1 file changed, 15 insertions(+), 5 deletions(-)
>
> diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
> index 74feb97..8762917 100644
> --- a/dlls/ntdll/loader.c
> +++ b/dlls/ntdll/loader.c
> @@ -64,7 +64,7 @@ WINE_DECLARE_DEBUG_CHANNEL(pid);
> typedef DWORD (CALLBACK *DLLENTRYPROC)(HMODULE,DWORD,LPVOID);
>
> static BOOL process_detaching = FALSE; /* set on process detach to avoid deadlocks with thread detach */
> -static int free_lib_count; /* recursion depth of LdrUnloadDll calls */
> +static int free_lib_count = 0; /* recursion depth of LdrUnloadDll calls */
This isn't really necessary, all static variables are initialized to zero.
>
> static const char * const reason_names[] =
> {
> @@ -2859,7 +2859,7 @@ static void MODULE_FlushModrefs(void)
> *
> * The loader_section must be locked while calling this function.
> */
> -static void MODULE_DecRefCount( WINE_MODREF *wm )
> +static void MODULE_DecRefCount( WINE_MODREF *wm , BOOL bDeps)
> {
> int i;
>
> @@ -2872,13 +2872,13 @@ static void MODULE_DecRefCount( WINE_MODREF *wm )
> --wm->ldr.LoadCount;
> TRACE("(%s) ldr.LoadCount: %d\n", debugstr_w(wm->ldr.BaseDllName.Buffer), wm->ldr.LoadCount );
>
> - if ( wm->ldr.LoadCount == 0 )
> + if ( wm->ldr.LoadCount == 0 && bDeps)
> {
> wm->ldr.Flags |= LDR_UNLOAD_IN_PROGRESS;
>
> for ( i = 0; i < wm->nDeps; i++ )
> if ( wm->deps[i] )
> - MODULE_DecRefCount( wm->deps[i] );
> + MODULE_DecRefCount( wm->deps[i] , TRUE );
>
> wm->ldr.Flags &= ~LDR_UNLOAD_IN_PROGRESS;
> }
> @@ -2893,6 +2893,7 @@ NTSTATUS WINAPI LdrUnloadDll( HMODULE hModule )
> {
> WINE_MODREF *wm;
> NTSTATUS retv = STATUS_SUCCESS;
> + static HMODULE first_recursion_module = 0;
>
> if (process_detaching) return retv;
>
> @@ -2900,13 +2901,19 @@ NTSTATUS WINAPI LdrUnloadDll( HMODULE hModule )
>
> RtlEnterCriticalSection( &loader_section );
>
> + if (0 == free_lib_count)
> + first_recursion_module = hModule;
> +
> free_lib_count++;
> if ((wm = get_modref( hModule )) != NULL)
> {
> TRACE("(%s) - START\n", debugstr_w(wm->ldr.BaseDllName.Buffer));
>
> /* Recursively decrement reference counts */
> - MODULE_DecRefCount( wm );
> + if (0 != free_lib_count && first_recursion_module == hModule)
> + MODULE_DecRefCount( wm , FALSE );
> + else
> + MODULE_DecRefCount( wm , TRUE );
At the location above free_lib_count will always be != 0 - this means that
your patch basically disables unloading of dependencies completely. Do you
have a small testcase for the problem you are trying to fix?
>
> /* Call process detach notifications */
> if ( free_lib_count <= 1 )
> @@ -2922,6 +2929,9 @@ NTSTATUS WINAPI LdrUnloadDll( HMODULE hModule )
>
> free_lib_count--;
>
> + if (0 == free_lib_count)
> + first_recursion_module = 0;
> +
> RtlLeaveCriticalSection( &loader_section );
>
> return retv;
> -- 2.10.2
>
>
>
More information about the wine-devel
mailing list