Implemented the SMTO_ABORTIFHUNG flag of SendMessageTimeout.

This commit is contained in:
Alexandre Julliard 2003-07-11 04:09:42 +00:00
parent 17c69c65aa
commit 09029b2878
6 changed files with 41 additions and 7 deletions

View file

@ -69,8 +69,9 @@ ULONG WINAPI RtlNtStatusToDosError( NTSTATUS status )
/* conversion tables */ /* conversion tables */
static const DWORD table_00000103[31] = static const DWORD table_00000102[32] =
{ {
ERROR_TIMEOUT, /* 00000102 (STATUS_TIMEOUT) */
ERROR_IO_PENDING, /* 00000103 (STATUS_PENDING) */ ERROR_IO_PENDING, /* 00000103 (STATUS_PENDING) */
ERROR_MR_MID_NOT_FOUND, /* 00000104 */ ERROR_MR_MID_NOT_FOUND, /* 00000104 */
ERROR_MORE_DATA, /* 00000105 (STATUS_MORE_ENTRIES) */ ERROR_MORE_DATA, /* 00000105 (STATUS_MORE_ENTRIES) */
@ -1333,7 +1334,7 @@ static const DWORD table_c0150001[14] =
static const struct error_table error_table[] = static const struct error_table error_table[] =
{ {
{ 0x00000103, 0x00000122, table_00000103 }, { 0x00000102, 0x00000122, table_00000102 },
{ 0x40000002, 0x4000000e, table_40000002 }, { 0x40000002, 0x4000000e, table_40000002 },
{ 0x40000370, 0x40000371, table_40000370 }, { 0x40000370, 0x40000371, table_40000370 },
{ 0x40020056, 0x40020057, table_40020056 }, { 0x40020056, 0x40020057, table_40020056 },

View file

@ -1663,12 +1663,14 @@ static BOOL put_message_in_queue( DWORD dest_tid, const struct send_message_info
{ {
req->id = dest_tid; req->id = dest_tid;
req->type = info->type; req->type = info->type;
req->flags = 0;
req->win = info->hwnd; req->win = info->hwnd;
req->msg = info->msg; req->msg = info->msg;
req->wparam = info->wparam; req->wparam = info->wparam;
req->lparam = info->lparam; req->lparam = info->lparam;
req->time = GetCurrentTime(); req->time = GetCurrentTime();
req->timeout = timeout; req->timeout = timeout;
if (info->flags & SMTO_ABORTIFHUNG) req->flags |= SEND_MSG_ABORT_IF_HUNG;
for (i = 0; i < data.count; i++) wine_server_add_data( req, data.data[i], data.size[i] ); for (i = 0; i < data.count; i++) wine_server_add_data( req, data.data[i], data.size[i] );
if ((res = wine_server_call( req ))) if ((res = wine_server_call( req )))
{ {
@ -1720,10 +1722,9 @@ static LRESULT retrieve_reply( const struct send_message_info *info,
info->hwnd, info->msg, SPY_GetMsgName(info->msg, info->hwnd), info->wparam, info->hwnd, info->msg, SPY_GetMsgName(info->msg, info->hwnd), info->wparam,
info->lparam, *result, status ); info->lparam, *result, status );
if (!status) return 1; /* MSDN states that last error is 0 on timeout, but at least NT4 returns ERROR_TIMEOUT */
if (status == STATUS_TIMEOUT) SetLastError(0); /* timeout */ if (status) SetLastError( RtlNtStatusToDosError(status) );
else SetLastError( RtlNtStatusToDosError(status) ); return !status;
return 0;
} }

View file

@ -2204,6 +2204,7 @@ struct send_message_request
struct request_header __header; struct request_header __header;
thread_id_t id; thread_id_t id;
int type; int type;
int flags;
user_handle_t win; user_handle_t win;
unsigned int msg; unsigned int msg;
unsigned int wparam; unsigned int wparam;
@ -2230,6 +2231,7 @@ enum message_type
MSG_POSTED, MSG_POSTED,
MSG_HARDWARE MSG_HARDWARE
}; };
#define SEND_MSG_ABORT_IF_HUNG 0x01
@ -3620,6 +3622,6 @@ union generic_reply
struct set_clipboard_info_reply set_clipboard_info_reply; struct set_clipboard_info_reply set_clipboard_info_reply;
}; };
#define SERVER_PROTOCOL_VERSION 114 #define SERVER_PROTOCOL_VERSION 115
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View file

@ -1564,6 +1564,7 @@ enum char_info_mode
@REQ(send_message) @REQ(send_message)
thread_id_t id; /* thread id */ thread_id_t id; /* thread id */
int type; /* message type (see below) */ int type; /* message type (see below) */
int flags; /* message flags (see below) */
user_handle_t win; /* window handle */ user_handle_t win; /* window handle */
unsigned int msg; /* message code */ unsigned int msg; /* message code */
unsigned int wparam; /* parameters */ unsigned int wparam; /* parameters */
@ -1586,6 +1587,7 @@ enum message_type
MSG_POSTED, /* posted message (from PostMessageW), always Unicode */ MSG_POSTED, /* posted message (from PostMessageW), always Unicode */
MSG_HARDWARE /* hardware message */ MSG_HARDWARE /* hardware message */
}; };
#define SEND_MSG_ABORT_IF_HUNG 0x01
/* Get a message from the current queue */ /* Get a message from the current queue */

View file

@ -125,6 +125,7 @@ struct msg_queue
struct timeout_user *timeout; /* timeout for next timer to expire */ struct timeout_user *timeout; /* timeout for next timer to expire */
struct thread_input *input; /* thread input descriptor */ struct thread_input *input; /* thread input descriptor */
struct hook_table *hooks; /* hook table */ struct hook_table *hooks; /* hook table */
struct timeval last_get_msg; /* time of last get message call */
}; };
static void msg_queue_dump( struct object *obj, int verbose ); static void msg_queue_dump( struct object *obj, int verbose );
@ -221,6 +222,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
queue->timeout = NULL; queue->timeout = NULL;
queue->input = (struct thread_input *)grab_object( input ); queue->input = (struct thread_input *)grab_object( input );
queue->hooks = NULL; queue->hooks = NULL;
gettimeofday( &queue->last_get_msg, NULL );
for (i = 0; i < NB_MSG_KINDS; i++) for (i = 0; i < NB_MSG_KINDS; i++)
queue->msg_list[i].first = queue->msg_list[i].last = NULL; queue->msg_list[i].first = queue->msg_list[i].last = NULL;
@ -589,6 +591,24 @@ static void cleanup_results( struct msg_queue *queue )
reply_message( queue, 0, STATUS_ACCESS_DENIED /*FIXME*/, 1, NULL, 0 ); reply_message( queue, 0, STATUS_ACCESS_DENIED /*FIXME*/, 1, NULL, 0 );
} }
/* check if the thread owning the queue is hung (not checking for messages) */
static int is_queue_hung( struct msg_queue *queue )
{
struct timeval now;
struct wait_queue_entry *entry;
gettimeofday( &now, NULL );
if (now.tv_sec - queue->last_get_msg.tv_sec <= 5)
return 0; /* less than 5 seconds since last get message -> not hung */
for (entry = queue->obj.head; entry; entry = entry->next)
{
if (entry->thread->queue == queue)
return 0; /* thread is waiting on queue -> not hung */
}
return 1;
}
static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry ) static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry )
{ {
struct msg_queue *queue = (struct msg_queue *)obj; struct msg_queue *queue = (struct msg_queue *)obj;
@ -1253,6 +1273,12 @@ DECL_HANDLER(send_message)
release_object( thread ); release_object( thread );
return; return;
} }
if (recv_queue && (req->flags & SEND_MSG_ABORT_IF_HUNG) && is_queue_hung(recv_queue))
{
set_error( STATUS_TIMEOUT );
release_object( thread );
return;
}
if ((msg = mem_alloc( sizeof(*msg) ))) if ((msg = mem_alloc( sizeof(*msg) )))
{ {
@ -1326,6 +1352,7 @@ DECL_HANDLER(get_message)
user_handle_t get_win = get_user_full_handle( req->get_win ); user_handle_t get_win = get_user_full_handle( req->get_win );
if (!queue) return; if (!queue) return;
gettimeofday( &queue->last_get_msg, NULL );
/* first of all release the hardware input lock if we own it */ /* first of all release the hardware input lock if we own it */
/* we'll grab it again if we find a hardware message */ /* we'll grab it again if we find a hardware message */

View file

@ -1834,6 +1834,7 @@ static void dump_send_message_request( const struct send_message_request *req )
{ {
fprintf( stderr, " id=%04x,", req->id ); fprintf( stderr, " id=%04x,", req->id );
fprintf( stderr, " type=%d,", req->type ); fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " flags=%d,", req->flags );
fprintf( stderr, " win=%p,", req->win ); fprintf( stderr, " win=%p,", req->win );
fprintf( stderr, " msg=%08x,", req->msg ); fprintf( stderr, " msg=%08x,", req->msg );
fprintf( stderr, " wparam=%08x,", req->wparam ); fprintf( stderr, " wparam=%08x,", req->wparam );