[PATCH] user32: Honor SMTO_ABORTIFHUNG while awaiting reply.

Shawn M. Chapla schapla at codeweavers.com
Fri May 7 13:22:22 CDT 2021


If the SMTO_ABORTIFHUNG flag is set, periodically time out (every 1000ms)
to check whether the thread from which a reply is expected has become
hung while the sending thread has been waiting for that reply.

While it is the case that, when necessary, the wineserver checks whether
a thread is hung before putting a message into its queue, this does not
account for cases in which a thread becomes hung after that message has
been enqueued but before it has been handled. In order to abort when
hung in those cases, client code must perform this check itself.

Signed-off-by: Shawn M. Chapla <schapla at codeweavers.com>
---
 dlls/user32/message.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index a54ecccc7cd..6e988a6aeb0 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -2949,15 +2949,17 @@ static HANDLE get_server_queue_handle(void)
  *
  * Wait until a sent message gets replied to.
  */
-static void wait_message_reply( UINT flags )
+static void wait_message_reply( UINT flags, HWND hwnd )
 {
     struct user_thread_info *thread_info = get_user_thread_info();
     HANDLE server_queue = get_server_queue_handle();
     unsigned int wake_mask = QS_SMRESULT | ((flags & SMTO_BLOCK) ? 0 : QS_SENDMESSAGE);
+    DWORD timeout = (flags & SMTO_ABORTIFHUNG) ? 1000 : INFINITE;
 
     for (;;)
     {
         unsigned int wake_bits = 0;
+        DWORD ret = 0;
 
         SERVER_START_REQ( set_queue_mask )
         {
@@ -2978,7 +2980,12 @@ static void wait_message_reply( UINT flags )
             continue;
         }
 
-        wow_handlers.wait_message( 1, &server_queue, INFINITE, wake_mask, 0 );
+        ret = wow_handlers.wait_message( 1, &server_queue, timeout, wake_mask, 0 );
+
+        /* If the wait call timed out and the window we're waiting
+           on is now hung, bail. */
+        if (ret == WAIT_TIMEOUT && IsHungAppWindow(hwnd))
+            return;
     }
 }
 
@@ -3156,7 +3163,7 @@ static LRESULT send_inter_thread_message( const struct send_message_info *info,
     /* there's no reply to wait for on notify/callback messages */
     if (info->type == MSG_NOTIFY || info->type == MSG_CALLBACK) return 1;
 
-    wait_message_reply( info->flags );
+    wait_message_reply( info->flags, info->hwnd );
     return retrieve_reply( info, reply_size, res_ptr );
 }
 
@@ -3309,7 +3316,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags )
     if (wait)
     {
         LRESULT ignored;
-        wait_message_reply( 0 );
+        wait_message_reply( 0, NULL );
         retrieve_reply( &info, 0, &ignored );
     }
     return ret;
-- 
2.28.0




More information about the wine-devel mailing list