Alexandre Julliard : ntdll: Add refcounting for .so builtin dlls.
Alexandre Julliard
julliard at winehq.org
Mon Mar 22 17:15:52 CDT 2021
Module: wine
Branch: master
Commit: 20c4ae45cecb2b08544880da5aeb7b9435d1ec65
URL: https://source.winehq.org/git/wine.git/?a=commit;h=20c4ae45cecb2b08544880da5aeb7b9435d1ec65
Author: Alexandre Julliard <julliard at winehq.org>
Date: Mon Mar 22 16:11:51 2021 +0100
ntdll: Add refcounting for .so builtin dlls.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/unix/loader.c | 4 ++-
dlls/ntdll/unix/unix_private.h | 1 +
dlls/ntdll/unix/virtual.c | 58 +++++++++++++++++++++++++++++-------------
3 files changed, 45 insertions(+), 18 deletions(-)
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
index 1c95b84e965..f7bdb055871 100644
--- a/dlls/ntdll/unix/loader.c
+++ b/dlls/ntdll/unix/loader.c
@@ -1456,7 +1456,9 @@ static void CDECL init_builtin_dll( void *module )
#endif
if (!(handle = get_builtin_so_handle( module ))) return;
- if (dlinfo( handle, RTLD_DI_LINKMAP, &map )) return;
+ if (dlinfo( handle, RTLD_DI_LINKMAP, &map )) map = NULL;
+ release_builtin_module( module );
+ if (!map) return;
for (dyn = map->l_ld; dyn->d_tag; dyn++)
{
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index 5877a00bac8..1307364d5d3 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -202,6 +202,7 @@ extern void virtual_set_force_exec( BOOL enable ) DECLSPEC_HIDDEN;
extern void virtual_set_large_address_space(void) DECLSPEC_HIDDEN;
extern void virtual_fill_image_information( const pe_image_info_t *pe_info,
SECTION_IMAGE_INFORMATION *info ) DECLSPEC_HIDDEN;
+extern NTSTATUS release_builtin_module( void *module ) DECLSPEC_HIDDEN;
extern void *get_builtin_so_handle( void *module ) DECLSPEC_HIDDEN;
extern NTSTATUS get_builtin_unix_info( void *module, const char **name, void **handle, void **entry ) DECLSPEC_HIDDEN;
extern NTSTATUS set_builtin_unix_info( void *module, const char *name, void *handle, void *entry ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index 4edc7d0261e..d00178d6261 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -85,14 +85,15 @@ static struct list reserved_areas = LIST_INIT(reserved_areas);
struct builtin_module
{
- struct list entry;
- dev_t dev;
- ino_t ino;
- void *handle;
- void *module;
- char *unix_name;
- void *unix_handle;
- void *unix_entry;
+ struct list entry;
+ unsigned int refcount;
+ dev_t dev;
+ ino_t ino;
+ void *handle;
+ void *module;
+ char *unix_name;
+ void *unix_handle;
+ void *unix_entry;
};
static struct list builtin_modules = LIST_INIT( builtin_modules );
@@ -569,8 +570,9 @@ static void add_builtin_module( void *module, void *handle, const struct stat *s
struct builtin_module *builtin;
if (!(builtin = malloc( sizeof(*builtin) ))) return;
- builtin->handle = handle;
- builtin->module = module;
+ builtin->handle = handle;
+ builtin->module = module;
+ builtin->refcount = 1;
builtin->unix_name = NULL;
builtin->unix_handle = NULL;
builtin->unix_entry = NULL;
@@ -589,19 +591,23 @@ static void add_builtin_module( void *module, void *handle, const struct stat *s
/***********************************************************************
- * remove_builtin_module
+ * release_builtin_module
*/
-static NTSTATUS remove_builtin_module( void *module )
+NTSTATUS release_builtin_module( void *module )
{
struct builtin_module *builtin;
LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry )
{
if (builtin->module != module) continue;
- list_remove( &builtin->entry );
- if (builtin->handle) dlclose( builtin->handle );
- if (builtin->unix_handle) dlclose( builtin->unix_handle );
- free( builtin );
+ if (!--builtin->refcount)
+ {
+ list_remove( &builtin->entry );
+ if (builtin->handle) dlclose( builtin->handle );
+ if (builtin->unix_handle) dlclose( builtin->unix_handle );
+ free( builtin->unix_name );
+ free( builtin );
+ }
return STATUS_SUCCESS;
}
return STATUS_INVALID_PARAMETER;
@@ -635,6 +641,7 @@ void *get_builtin_so_handle( void *module )
{
if (builtin->module != module) continue;
ret = builtin->handle;
+ if (ret) builtin->refcount++;
break;
}
server_leave_uninterrupted_section( &virtual_mutex, &sigset );
@@ -4374,6 +4381,23 @@ NTSTATUS WINAPI NtUnmapViewOfSection( HANDLE process, PVOID addr )
server_enter_uninterrupted_section( &virtual_mutex, &sigset );
if ((view = find_view( addr, 0 )) && !is_view_valloc( view ))
{
+ if (view->protect & VPROT_SYSTEM)
+ {
+ struct builtin_module *builtin;
+
+ LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry )
+ {
+ if (builtin->module != view->base) continue;
+ if (builtin->refcount > 1)
+ {
+ TRACE( "not freeing in-use builtin %p\n", view->base );
+ builtin->refcount--;
+ server_leave_uninterrupted_section( &virtual_mutex, &sigset );
+ return STATUS_SUCCESS;
+ }
+ }
+ }
+
SERVER_START_REQ( unmap_view )
{
req->base = wine_server_client_ptr( view->base );
@@ -4382,7 +4406,7 @@ NTSTATUS WINAPI NtUnmapViewOfSection( HANDLE process, PVOID addr )
SERVER_END_REQ;
if (!status)
{
- if (view->protect & SEC_IMAGE) remove_builtin_module( view->base );
+ if (view->protect & SEC_IMAGE) release_builtin_module( view->base );
delete_view( view );
}
else FIXME( "failed to unmap %p %x\n", view->base, status );
More information about the wine-cvs
mailing list