mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
server-Desktop_Refcount: Remove patch set.
This was first added in 78db8b7950c18c7882f800449029c4b9662c25f0 with the message "Added patch to fix possible leak of explorer.exe processes and implement proper desktop refcounting." The message of course suggests that even then no application was known that actually depended on this. In practice this seems wrong, also: once all non-system processes other than explorer have terminated, the only way explorer.exe can remain alive is if a system process holds a reference to explorer. The only relevant system processes are services, and services cannot display a GUI [this is enforced since Vista], so this should never be the case.
This commit is contained in:
parent
7fc716aa5f
commit
71ac12a8e3
@ -6,5 +6,4 @@ Depends: server-Realtime_Priority
|
||||
Depends: advapi32-Token_Integrity_Level
|
||||
Depends: ntdll-Junction_Points
|
||||
Depends: user32-rawinput-mouse
|
||||
Depends: server-Desktop_Refcount
|
||||
Disabled: true
|
File diff suppressed because it is too large
Load Diff
@ -1,266 +0,0 @@
|
||||
From 7d35e2176637947cd0d8072830408db42a4037d8 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Fri, 4 Dec 2015 01:22:29 +0100
|
||||
Subject: [PATCH] server: Track desktop handle count more correctly.
|
||||
|
||||
Desktop objects should stay valid, as long as there is a handle from a
|
||||
(non-system) process. Counting only process->desktop references is not
|
||||
sufficient in practice, and causes explorer.exe process leaks.
|
||||
|
||||
Signed-off-by: Sebastian Lackner <sebastian@fds-team.de>
|
||||
---
|
||||
programs/explorer/desktop.c | 18 +++++++-
|
||||
server/handle.c | 3 +-
|
||||
server/handle.h | 2 +-
|
||||
server/process.c | 1 -
|
||||
server/sock.c | 2 +-
|
||||
server/winstation.c | 88 +++++++++++++++++++------------------
|
||||
6 files changed, 66 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c
|
||||
index 2857fcfca..f45bd9d43 100644
|
||||
--- a/programs/explorer/desktop.c
|
||||
+++ b/programs/explorer/desktop.c
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(explorer);
|
||||
|
||||
+extern HANDLE CDECL __wine_make_process_system(void);
|
||||
+
|
||||
#define DESKTOP_CLASS_ATOM ((LPCWSTR)MAKEINTATOM(32769))
|
||||
#define DESKTOP_ALL_ACCESS 0x01ff
|
||||
|
||||
@@ -1009,8 +1011,22 @@ void manage_desktop( WCHAR *arg )
|
||||
/* run the desktop message loop */
|
||||
if (hwnd)
|
||||
{
|
||||
+ HANDLE exit_event = __wine_make_process_system();
|
||||
WINE_TRACE( "desktop message loop starting on hwnd %p\n", hwnd );
|
||||
- while (GetMessageW( &msg, 0, 0, 0 )) DispatchMessageW( &msg );
|
||||
+ while (exit_event != NULL && MsgWaitForMultipleObjectsEx( 1,
|
||||
+ &exit_event, INFINITE, QS_ALLINPUT, 0 ) == WAIT_OBJECT_0 + 1)
|
||||
+ {
|
||||
+ while (PeekMessageW( &msg, NULL, 0, 0, PM_REMOVE ))
|
||||
+ {
|
||||
+ if (msg.message == WM_QUIT)
|
||||
+ {
|
||||
+ exit_event = NULL;
|
||||
+ break;
|
||||
+ }
|
||||
+ TranslateMessage( &msg );
|
||||
+ DispatchMessageW( &msg );
|
||||
+ }
|
||||
+ }
|
||||
WINE_TRACE( "desktop message loop exiting for hwnd %p\n", hwnd );
|
||||
}
|
||||
|
||||
diff --git a/server/handle.c b/server/handle.c
|
||||
index 879098aee..0aa5aa52b 100644
|
||||
--- a/server/handle.c
|
||||
+++ b/server/handle.c
|
||||
@@ -499,7 +499,7 @@ obj_handle_t find_inherited_handle( struct process *process, const struct object
|
||||
/* enumerate handles of a given type */
|
||||
/* this is needed for window stations and desktops */
|
||||
obj_handle_t enumerate_handles( struct process *process, const struct object_ops *ops,
|
||||
- unsigned int *index )
|
||||
+ obj_handle_t *index, struct object **obj )
|
||||
{
|
||||
struct handle_table *table = process->handles;
|
||||
unsigned int i;
|
||||
@@ -512,6 +512,7 @@ obj_handle_t enumerate_handles( struct process *process, const struct object_ops
|
||||
if (!entry->ptr) continue;
|
||||
if (entry->ptr->ops != ops) continue;
|
||||
*index = i + 1;
|
||||
+ if (obj) *obj = grab_object( entry->ptr );
|
||||
return index_to_handle(i);
|
||||
}
|
||||
return 0;
|
||||
diff --git a/server/handle.h b/server/handle.h
|
||||
index f1deb79fb..13478368f 100644
|
||||
--- a/server/handle.h
|
||||
+++ b/server/handle.h
|
||||
@@ -49,7 +49,7 @@ extern obj_handle_t open_object( struct process *process, obj_handle_t parent, u
|
||||
unsigned int attr );
|
||||
extern obj_handle_t find_inherited_handle( struct process *process, const struct object_ops *ops );
|
||||
extern obj_handle_t enumerate_handles( struct process *process, const struct object_ops *ops,
|
||||
- unsigned int *index );
|
||||
+ unsigned int *index, struct object **obj );
|
||||
extern void close_process_handles( struct process *process );
|
||||
extern struct handle_table *alloc_handle_table( struct process *process, int count );
|
||||
extern struct handle_table *copy_handle_table( struct process *process, struct process *parent );
|
||||
diff --git a/server/process.c b/server/process.c
|
||||
index e6568eceb..3221b15da 100644
|
||||
--- a/server/process.c
|
||||
+++ b/server/process.c
|
||||
@@ -899,7 +899,6 @@ static void process_killed( struct process *process )
|
||||
|
||||
assert( list_empty( &process->thread_list ));
|
||||
process->end_time = current_time;
|
||||
- if (!process->is_system) close_process_desktop( process );
|
||||
process->winstation = 0;
|
||||
process->desktop = 0;
|
||||
close_process_handles( process );
|
||||
diff --git a/server/sock.c b/server/sock.c
|
||||
index f951f23d6..d373768c9 100644
|
||||
--- a/server/sock.c
|
||||
+++ b/server/sock.c
|
||||
@@ -1344,6 +1344,6 @@ DECL_HANDLER(socket_cleanup)
|
||||
unsigned int index = 0;
|
||||
obj_handle_t sock;
|
||||
|
||||
- while ((sock = enumerate_handles(current->process, &sock_ops, &index)))
|
||||
+ while ((sock = enumerate_handles(current->process, &sock_ops, &index, NULL)))
|
||||
close_handle(current->process, sock);
|
||||
}
|
||||
diff --git a/server/winstation.c b/server/winstation.c
|
||||
index d7e8a5c80..f9c005496 100644
|
||||
--- a/server/winstation.c
|
||||
+++ b/server/winstation.c
|
||||
@@ -53,6 +53,7 @@ static unsigned int winstation_map_access( struct object *obj, unsigned int acce
|
||||
static void desktop_dump( struct object *obj, int verbose );
|
||||
static struct object_type *desktop_get_type( struct object *obj );
|
||||
static int desktop_link_name( struct object *obj, struct object_name *name, struct object *parent );
|
||||
+static void desktop_alloc_handle( struct object *obj, struct process *process, obj_handle_t handle );
|
||||
static int desktop_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
|
||||
static void desktop_destroy( struct object *obj );
|
||||
static unsigned int desktop_map_access( struct object *obj, unsigned int access );
|
||||
@@ -103,7 +104,7 @@ static const struct object_ops desktop_ops =
|
||||
default_unlink_name, /* unlink_name */
|
||||
no_open_file, /* open_file */
|
||||
no_kernel_obj_list, /* get_kernel_obj_list */
|
||||
- no_alloc_handle, /* alloc_handle */
|
||||
+ desktop_alloc_handle, /* alloc_handle */
|
||||
desktop_close_handle, /* close_handle */
|
||||
desktop_destroy /* destroy */
|
||||
};
|
||||
@@ -275,14 +276,54 @@ static int desktop_link_name( struct object *obj, struct object_name *name, stru
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static void close_desktop_timeout( void *private )
|
||||
+{
|
||||
+ struct desktop *desktop = private;
|
||||
+
|
||||
+ desktop->close_timeout = NULL;
|
||||
+ unlink_named_object( &desktop->obj ); /* make sure no other process can open it */
|
||||
+ post_desktop_message( desktop, WM_CLOSE, 0, 0 ); /* and signal the owner to quit */
|
||||
+}
|
||||
+
|
||||
+/* remove a user of the desktop and start the close timeout if necessary */
|
||||
+static void remove_desktop_user( struct desktop *desktop )
|
||||
+{
|
||||
+ assert( desktop->users > 0 );
|
||||
+ desktop->users--;
|
||||
+
|
||||
+ if (!desktop->users && get_top_window_owner( desktop ))
|
||||
+ {
|
||||
+ assert( !desktop->close_timeout );
|
||||
+ desktop->close_timeout = add_timeout_user( -TICKS_PER_SEC, close_desktop_timeout, desktop );
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void desktop_alloc_handle( struct object *obj, struct process *process, obj_handle_t handle )
|
||||
+{
|
||||
+ struct desktop *desktop = (struct desktop *)obj;
|
||||
+ if (process->is_system) return;
|
||||
+
|
||||
+ desktop->users++;
|
||||
+ if (desktop->close_timeout)
|
||||
+ {
|
||||
+ remove_timeout_user( desktop->close_timeout );
|
||||
+ desktop->close_timeout = NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int desktop_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
|
||||
{
|
||||
+ struct desktop *desktop = (struct desktop *)obj;
|
||||
struct thread *thread;
|
||||
|
||||
/* check if the handle is currently used by the process or one of its threads */
|
||||
if (process->desktop == handle) return 0;
|
||||
LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry )
|
||||
if (thread->desktop == handle) return 0;
|
||||
+
|
||||
+ if (!process->is_system)
|
||||
+ remove_desktop_user( desktop );
|
||||
+
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -290,6 +331,7 @@ static void desktop_destroy( struct object *obj )
|
||||
{
|
||||
struct desktop *desktop = (struct desktop *)obj;
|
||||
|
||||
+ assert( !desktop->users );
|
||||
free_hotkeys( desktop, 0 );
|
||||
if (desktop->top_window) destroy_window( desktop->top_window );
|
||||
if (desktop->msg_window) destroy_window( desktop->msg_window );
|
||||
@@ -316,40 +358,6 @@ struct desktop *get_thread_desktop( struct thread *thread, unsigned int access )
|
||||
return get_desktop_obj( thread->process, thread->desktop, access );
|
||||
}
|
||||
|
||||
-static void close_desktop_timeout( void *private )
|
||||
-{
|
||||
- struct desktop *desktop = private;
|
||||
-
|
||||
- desktop->close_timeout = NULL;
|
||||
- unlink_named_object( &desktop->obj ); /* make sure no other process can open it */
|
||||
- post_desktop_message( desktop, WM_CLOSE, 0, 0 ); /* and signal the owner to quit */
|
||||
-}
|
||||
-
|
||||
-/* add a user of the desktop and cancel the close timeout */
|
||||
-static void add_desktop_user( struct desktop *desktop )
|
||||
-{
|
||||
- desktop->users++;
|
||||
- if (desktop->close_timeout)
|
||||
- {
|
||||
- remove_timeout_user( desktop->close_timeout );
|
||||
- desktop->close_timeout = NULL;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-/* remove a user of the desktop and start the close timeout if necessary */
|
||||
-static void remove_desktop_user( struct desktop *desktop )
|
||||
-{
|
||||
- assert( desktop->users > 0 );
|
||||
- desktop->users--;
|
||||
-
|
||||
- /* if we have one remaining user, it has to be the manager of the desktop window */
|
||||
- if (desktop->users == 1 && get_top_window_owner( desktop ))
|
||||
- {
|
||||
- assert( !desktop->close_timeout );
|
||||
- desktop->close_timeout = add_timeout_user( -TICKS_PER_SEC, close_desktop_timeout, desktop );
|
||||
- }
|
||||
-}
|
||||
-
|
||||
/* set the process default desktop handle */
|
||||
void set_process_default_desktop( struct process *process, struct desktop *desktop,
|
||||
obj_handle_t handle )
|
||||
@@ -366,12 +374,6 @@ void set_process_default_desktop( struct process *process, struct desktop *deskt
|
||||
LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry )
|
||||
if (!thread->desktop) thread->desktop = handle;
|
||||
|
||||
- if (!process->is_system && desktop != old_desktop)
|
||||
- {
|
||||
- add_desktop_user( desktop );
|
||||
- if (old_desktop) remove_desktop_user( old_desktop );
|
||||
- }
|
||||
-
|
||||
if (old_desktop) release_object( old_desktop );
|
||||
}
|
||||
|
||||
@@ -421,8 +423,8 @@ done:
|
||||
void close_process_desktop( struct process *process )
|
||||
{
|
||||
struct desktop *desktop;
|
||||
-
|
||||
- if (process->desktop && (desktop = get_desktop_obj( process, process->desktop, 0 )))
|
||||
+ unsigned int i = 0;
|
||||
+ while (enumerate_handles( process, &desktop_ops, &i, (struct object **)&desktop ))
|
||||
{
|
||||
remove_desktop_user( desktop );
|
||||
release_object( desktop );
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,4 +0,0 @@
|
||||
Fixes: Fix possible leak of explorer.exe processes and implement proper desktop refcounting
|
||||
Fixes: [46967] GOG Galaxy doesn't run in virtual desktop.
|
||||
# Needs work
|
||||
Disabled: true
|
@ -1,6 +1,4 @@
|
||||
Fixes: Report correct ObjectName for NamedPipe wineserver objects
|
||||
# Depends: kernel32-Named_Pipe
|
||||
Depends: server-Desktop_Refcount
|
||||
# This was originally written for msys2's strace.exe. It was broken by
|
||||
# 59dd8ba..6098af8. Since msys2 has been broken in Wine for a while now, this
|
||||
# really isn't worth fixing.
|
||||
|
Loading…
x
Reference in New Issue
Block a user