[PATCH] user32: Always process sent messages when sending inter-thread messages.

Zebediah Figura z.figura12 at gmail.com
Tue Jan 23 18:18:33 CST 2018


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
Sometimes the sent message will be processed before the loop has had time to
execute once, and sent messages will remain in the queue unprocessed. This
never happens on Windows, although it is not quite clear whether this is
guaranteed or whether it is simply due to consistency in thread scheduling.
MSDN states:

 However, the sending thread will process incoming nonqueued messages while
 waiting for its message to be processed.

which is somewhat ambiguous.

We have tests in Wine (namely in ole32:clipboard) which were failing
intermittently because sent messages were sometimes not being processed while
executing SendMessageTimeout(). This test has never failed on Windows, in any
configuration tracked on test.winehq.org, and so I am inclined to conclude
that this logic matches Windows' behaviour.

 dlls/user32/message.c   |  2 +-
 dlls/user32/tests/msg.c | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index 172d659..81844e3 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -3015,13 +3015,13 @@ static void wait_message_reply( UINT flags )
 
         thread_info->wake_mask = thread_info->changed_mask = 0;
 
-        if (wake_bits & QS_SMRESULT) return;  /* got a result */
         if (wake_bits & QS_SENDMESSAGE)
         {
             /* Process the sent message immediately */
             process_sent_messages();
             continue;
         }
+        if (wake_bits & QS_SMRESULT) return;  /* got a result */
 
         wow_handlers.wait_message( 1, &server_queue, INFINITE, wake_mask, 0 );
     }
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index f391ab9..082b560 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -16633,6 +16633,37 @@ static void test_DoubleSetCapture(void)
     DestroyWindow(hwnd);
 }
 
+static DWORD WINAPI send_notify_message_thread(void *param)
+{
+    SendNotifyMessageA((HWND) param, WM_USER, 0, 0);
+    return 0;
+}
+
+static void test_SendMessage_pump(void)
+{
+    /* Sending a message to another thread's window should process sent messages
+     * currently in the queue. On Windows this always happens, i.e. we never
+     * fail to do so if we've already received a reply. */
+
+    HWND hwnd;
+    HANDLE thread;
+
+    hwnd = CreateWindowA("TestWindowClass", "test_SendMessage_pump", 0,
+                         100, 100, 200, 200, 0, 0, 0, 0);
+    ok(hwnd != NULL, "Failed to create window\n");
+    flush_sequence();
+
+    thread = CreateThread(0, 0, send_notify_message_thread, hwnd, 0, 0);
+    ok(WaitForSingleObject(thread, 1000) == WAIT_OBJECT_0, "wait failed\n");
+    ok_sequence(WmEmptySeq, "no messages", FALSE);
+
+    SendMessageA(GetDesktopWindow(), WM_NULL, 0, 0);
+    ok_sequence(WmUser, "SendMessage() pump", FALSE);
+
+    CloseHandle(thread);
+    DestroyWindow(hwnd);
+}
+
 static void init_funcs(void)
 {
     HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
@@ -16777,6 +16808,7 @@ START_TEST(msg)
     test_TrackPopupMenu();
     test_TrackPopupMenuEmpty();
     test_DoubleSetCapture();
+    test_SendMessage_pump();
     /* keep it the last test, under Windows it tends to break the tests
      * which rely on active/foreground windows being correct.
      */
-- 
2.7.4




More information about the wine-devel mailing list