wined3d: Use a separate mutex for wndproc_table access.
If CreateDevice is called with hFocusWindow belonging to another thread, then any code that does SendMessage (or equivalent) to the window while holding the main wined3d mutex causes a deadlock, because wined3d_wndproc tries to acquire the same mutex for wndproc_table access.
This commit is contained in:
parent
efaa068cd1
commit
b5e04640cc
|
@ -60,6 +60,16 @@ static CRITICAL_SECTION_DEBUG wined3d_cs_debug =
|
||||||
};
|
};
|
||||||
static CRITICAL_SECTION wined3d_cs = {&wined3d_cs_debug, -1, 0, 0, 0, 0};
|
static CRITICAL_SECTION wined3d_cs = {&wined3d_cs_debug, -1, 0, 0, 0, 0};
|
||||||
|
|
||||||
|
static CRITICAL_SECTION wined3d_wndproc_cs;
|
||||||
|
static CRITICAL_SECTION_DEBUG wined3d_wndproc_cs_debug =
|
||||||
|
{
|
||||||
|
0, 0, &wined3d_wndproc_cs,
|
||||||
|
{&wined3d_wndproc_cs_debug.ProcessLocksList,
|
||||||
|
&wined3d_wndproc_cs_debug.ProcessLocksList},
|
||||||
|
0, 0, {(DWORD_PTR)(__FILE__ ": wined3d_wndproc_cs")}
|
||||||
|
};
|
||||||
|
static CRITICAL_SECTION wined3d_wndproc_cs = {&wined3d_wndproc_cs_debug, -1, 0, 0, 0, 0};
|
||||||
|
|
||||||
/* When updating default value here, make sure to update winecfg as well,
|
/* When updating default value here, make sure to update winecfg as well,
|
||||||
* where appropriate. */
|
* where appropriate. */
|
||||||
struct wined3d_settings wined3d_settings =
|
struct wined3d_settings wined3d_settings =
|
||||||
|
@ -381,6 +391,16 @@ void WINAPI wined3d_mutex_unlock(void)
|
||||||
LeaveCriticalSection(&wined3d_cs);
|
LeaveCriticalSection(&wined3d_cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wined3d_wndproc_mutex_lock(void)
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&wined3d_wndproc_cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wined3d_wndproc_mutex_unlock(void)
|
||||||
|
{
|
||||||
|
LeaveCriticalSection(&wined3d_wndproc_cs);
|
||||||
|
}
|
||||||
|
|
||||||
static struct wined3d_wndproc *wined3d_find_wndproc(HWND window)
|
static struct wined3d_wndproc *wined3d_find_wndproc(HWND window)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
@ -403,12 +423,12 @@ static LRESULT CALLBACK wined3d_wndproc(HWND window, UINT message, WPARAM wparam
|
||||||
BOOL unicode;
|
BOOL unicode;
|
||||||
WNDPROC proc;
|
WNDPROC proc;
|
||||||
|
|
||||||
wined3d_mutex_lock();
|
wined3d_wndproc_mutex_lock();
|
||||||
entry = wined3d_find_wndproc(window);
|
entry = wined3d_find_wndproc(window);
|
||||||
|
|
||||||
if (!entry)
|
if (!entry)
|
||||||
{
|
{
|
||||||
wined3d_mutex_unlock();
|
wined3d_wndproc_mutex_unlock();
|
||||||
ERR("Window %p is not registered with wined3d.\n", window);
|
ERR("Window %p is not registered with wined3d.\n", window);
|
||||||
return DefWindowProcW(window, message, wparam, lparam);
|
return DefWindowProcW(window, message, wparam, lparam);
|
||||||
}
|
}
|
||||||
|
@ -416,7 +436,7 @@ static LRESULT CALLBACK wined3d_wndproc(HWND window, UINT message, WPARAM wparam
|
||||||
device = entry->device;
|
device = entry->device;
|
||||||
unicode = entry->unicode;
|
unicode = entry->unicode;
|
||||||
proc = entry->proc;
|
proc = entry->proc;
|
||||||
wined3d_mutex_unlock();
|
wined3d_wndproc_mutex_unlock();
|
||||||
|
|
||||||
return device_process_message(device, window, unicode, message, wparam, lparam, proc);
|
return device_process_message(device, window, unicode, message, wparam, lparam, proc);
|
||||||
}
|
}
|
||||||
|
@ -425,11 +445,11 @@ BOOL wined3d_register_window(HWND window, struct wined3d_device *device)
|
||||||
{
|
{
|
||||||
struct wined3d_wndproc *entry;
|
struct wined3d_wndproc *entry;
|
||||||
|
|
||||||
wined3d_mutex_lock();
|
wined3d_wndproc_mutex_lock();
|
||||||
|
|
||||||
if (wined3d_find_wndproc(window))
|
if (wined3d_find_wndproc(window))
|
||||||
{
|
{
|
||||||
wined3d_mutex_unlock();
|
wined3d_wndproc_mutex_unlock();
|
||||||
WARN("Window %p is already registered with wined3d.\n", window);
|
WARN("Window %p is already registered with wined3d.\n", window);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -444,7 +464,7 @@ BOOL wined3d_register_window(HWND window, struct wined3d_device *device)
|
||||||
|
|
||||||
if (!new_entries)
|
if (!new_entries)
|
||||||
{
|
{
|
||||||
wined3d_mutex_unlock();
|
wined3d_wndproc_mutex_unlock();
|
||||||
ERR("Failed to grow table.\n");
|
ERR("Failed to grow table.\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -465,7 +485,7 @@ BOOL wined3d_register_window(HWND window, struct wined3d_device *device)
|
||||||
entry->proc = (WNDPROC)SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)wined3d_wndproc);
|
entry->proc = (WNDPROC)SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)wined3d_wndproc);
|
||||||
entry->device = device;
|
entry->device = device;
|
||||||
|
|
||||||
wined3d_mutex_unlock();
|
wined3d_wndproc_mutex_unlock();
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -475,11 +495,11 @@ void wined3d_unregister_window(HWND window)
|
||||||
struct wined3d_wndproc *entry, *last;
|
struct wined3d_wndproc *entry, *last;
|
||||||
LONG_PTR proc;
|
LONG_PTR proc;
|
||||||
|
|
||||||
wined3d_mutex_lock();
|
wined3d_wndproc_mutex_lock();
|
||||||
|
|
||||||
if (!(entry = wined3d_find_wndproc(window)))
|
if (!(entry = wined3d_find_wndproc(window)))
|
||||||
{
|
{
|
||||||
wined3d_mutex_unlock();
|
wined3d_wndproc_mutex_unlock();
|
||||||
ERR("Window %p is not registered with wined3d.\n", window);
|
ERR("Window %p is not registered with wined3d.\n", window);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -489,7 +509,7 @@ void wined3d_unregister_window(HWND window)
|
||||||
proc = GetWindowLongPtrW(window, GWLP_WNDPROC);
|
proc = GetWindowLongPtrW(window, GWLP_WNDPROC);
|
||||||
if (proc != (LONG_PTR)wined3d_wndproc)
|
if (proc != (LONG_PTR)wined3d_wndproc)
|
||||||
{
|
{
|
||||||
wined3d_mutex_unlock();
|
wined3d_wndproc_mutex_unlock();
|
||||||
WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n",
|
WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n",
|
||||||
window, proc, wined3d_wndproc);
|
window, proc, wined3d_wndproc);
|
||||||
return;
|
return;
|
||||||
|
@ -502,7 +522,7 @@ void wined3d_unregister_window(HWND window)
|
||||||
proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
|
proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
|
||||||
if (proc != (LONG_PTR)wined3d_wndproc)
|
if (proc != (LONG_PTR)wined3d_wndproc)
|
||||||
{
|
{
|
||||||
wined3d_mutex_unlock();
|
wined3d_wndproc_mutex_unlock();
|
||||||
WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n",
|
WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n",
|
||||||
window, proc, wined3d_wndproc);
|
window, proc, wined3d_wndproc);
|
||||||
return;
|
return;
|
||||||
|
@ -514,7 +534,7 @@ void wined3d_unregister_window(HWND window)
|
||||||
last = &wndproc_table.entries[--wndproc_table.count];
|
last = &wndproc_table.entries[--wndproc_table.count];
|
||||||
if (entry != last) *entry = *last;
|
if (entry != last) *entry = *last;
|
||||||
|
|
||||||
wined3d_mutex_unlock();
|
wined3d_wndproc_mutex_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At process attach */
|
/* At process attach */
|
||||||
|
|
Loading…
Reference in New Issue