Piotr Caban : winebus.sys: Stop deviceloop_thread to avoid crash on driver unload.

Alexandre Julliard julliard at winehq.org
Tue Sep 17 16:22:49 CDT 2019


Module: wine
Branch: master
Commit: 90fa9967bcd571ce880f7cdd522a5b0b96801a13
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=90fa9967bcd571ce880f7cdd522a5b0b96801a13

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Tue Sep 17 13:45:42 2019 +0200

winebus.sys: Stop deviceloop_thread to avoid crash on driver unload.

Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/winebus.sys/bus_udev.c | 39 ++++++++++++++++++++++++++++++++-------
 1 file changed, 32 insertions(+), 7 deletions(-)

diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c
index 20841b09ae..3ed1b029e8 100644
--- a/dlls/winebus.sys/bus_udev.c
+++ b/dlls/winebus.sys/bus_udev.c
@@ -92,6 +92,8 @@ WINE_DECLARE_DEBUG_CHANNEL(hid_report);
 static struct udev *udev_context = NULL;
 static DWORD disable_hidraw = 0;
 static DWORD disable_input = 0;
+static HANDLE deviceloop_handle;
+static int deviceloop_control[2];
 
 static const WCHAR hidraw_busidW[] = {'H','I','D','R','A','W',0};
 static const WCHAR lnxev_busidW[] = {'L','N','X','E','V',0};
@@ -1453,15 +1455,20 @@ static DWORD CALLBACK deviceloop_thread(void *args)
 {
     struct udev_monitor *monitor;
     HANDLE init_done = args;
-    struct pollfd pfd;
+    struct pollfd pfd[2];
 
-    monitor = create_monitor(&pfd);
+    pfd[1].fd = deviceloop_control[0];
+    pfd[1].events = POLLIN;
+    pfd[1].revents = 0;
+
+    monitor = create_monitor(&pfd[0]);
     build_initial_deviceset();
     SetEvent(init_done);
 
     while (monitor)
     {
-        if (poll(&pfd, 1, -1) <= 0) continue;
+        if (poll(pfd, 2, -1) <= 0) continue;
+        if (pfd[1].revents) break;
         process_monitor_event(monitor);
     }
 
@@ -1474,6 +1481,12 @@ static DWORD CALLBACK deviceloop_thread(void *args)
 void udev_driver_unload( void )
 {
     TRACE("Unload Driver\n");
+
+    write(deviceloop_control[1], "q", 1);
+    WaitForSingleObject(deviceloop_handle, INFINITE);
+    close(deviceloop_control[0]);
+    close(deviceloop_control[1]);
+    CloseHandle(deviceloop_handle);
 }
 
 NTSTATUS udev_driver_init(void)
@@ -1485,10 +1498,16 @@ NTSTATUS udev_driver_init(void)
     static const WCHAR input_disabledW[] = {'D','i','s','a','b','l','e','I','n','p','u','t',0};
     static const UNICODE_STRING input_disabled = {sizeof(input_disabledW) - sizeof(WCHAR), sizeof(input_disabledW), (WCHAR*)input_disabledW};
 
+    if (pipe(deviceloop_control) != 0)
+    {
+        ERR("Control pipe creation failed\n");
+        return STATUS_UNSUCCESSFUL;
+    }
+
     if (!(udev_context = udev_new()))
     {
         ERR("Can't create udev object\n");
-        return STATUS_UNSUCCESSFUL;
+        goto error;
     }
 
     disable_hidraw = check_bus_option(&hidraw_disabled, 0);
@@ -1511,17 +1530,23 @@ NTSTATUS udev_driver_init(void)
 
     result = WaitForMultipleObjects(2, events, FALSE, INFINITE);
     CloseHandle(events[0]);
-    CloseHandle(events[1]);
     if (result == WAIT_OBJECT_0)
     {
+        deviceloop_handle = events[1];
         TRACE("Initialization successful\n");
         return STATUS_SUCCESS;
     }
+    CloseHandle(events[1]);
 
 error:
     ERR("Failed to initialize udev device thread\n");
-    udev_unref(udev_context);
-    udev_context = NULL;
+    close(deviceloop_control[0]);
+    close(deviceloop_control[1]);
+    if (udev_context)
+    {
+        udev_unref(udev_context);
+        udev_context = NULL;
+    }
     return STATUS_UNSUCCESSFUL;
 }
 




More information about the wine-cvs mailing list