diff options
| author | Andrew Innes | 1998-12-28 19:42:26 +0000 |
|---|---|---|
| committer | Andrew Innes | 1998-12-28 19:42:26 +0000 |
| commit | 3ef68e6be28a206cc531b0fe113ad301b3447195 (patch) | |
| tree | 491633d6ce383f974cb36337df711102970bbd45 /src | |
| parent | 82e7c0a907a11f84d9eaf9750266db104974e9ab (diff) | |
| download | emacs-3ef68e6be28a206cc531b0fe113ad301b3447195.tar.gz emacs-3ef68e6be28a206cc531b0fe113ad301b3447195.zip | |
(w32_msg_pump): Ignore WM_NULL message posted to thread
by complete_deferred_msg.
(post_character_message): Cancel all deferred messages when
quit_char is typed, in order to break out of potential deadlocks.
(cancel_all_deferred_msgs): New function.
(complete_deferred_msg): Don't abort if msg not found; may have
been cancelled.
(Fw32_reconstruct_hot_key): Use pre-interned symbols.
(Fw32_send_sys_command): Wait for system command to
complete before returning.
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32fns.c | 135 |
1 files changed, 90 insertions, 45 deletions
diff --git a/src/w32fns.c b/src/w32fns.c index 47423f466f8..000ebb54018 100644 --- a/src/w32fns.c +++ b/src/w32fns.c | |||
| @@ -3355,45 +3355,6 @@ unregister_hot_keys (hwnd) | |||
| 3355 | } | 3355 | } |
| 3356 | } | 3356 | } |
| 3357 | 3357 | ||
| 3358 | static void | ||
| 3359 | post_character_message (hwnd, msg, wParam, lParam, modifiers) | ||
| 3360 | HWND hwnd; | ||
| 3361 | UINT msg; | ||
| 3362 | WPARAM wParam; | ||
| 3363 | LPARAM lParam; | ||
| 3364 | DWORD modifiers; | ||
| 3365 | |||
| 3366 | { | ||
| 3367 | W32Msg wmsg; | ||
| 3368 | |||
| 3369 | wmsg.dwModifiers = modifiers; | ||
| 3370 | |||
| 3371 | /* Detect quit_char and set quit-flag directly. Note that we | ||
| 3372 | still need to post a message to ensure the main thread will be | ||
| 3373 | woken up if blocked in sys_select(), but we do NOT want to post | ||
| 3374 | the quit_char message itself (because it will usually be as if | ||
| 3375 | the user had typed quit_char twice). Instead, we post a dummy | ||
| 3376 | message that has no particular effect. */ | ||
| 3377 | { | ||
| 3378 | int c = wParam; | ||
| 3379 | if (isalpha (c) && wmsg.dwModifiers == ctrl_modifier) | ||
| 3380 | c = make_ctrl_char (c) & 0377; | ||
| 3381 | if (c == quit_char) | ||
| 3382 | { | ||
| 3383 | Vquit_flag = Qt; | ||
| 3384 | |||
| 3385 | /* The choice of message is somewhat arbitrary, as long as | ||
| 3386 | the main thread handler just ignores it. */ | ||
| 3387 | msg = WM_NULL; | ||
| 3388 | |||
| 3389 | /* Interrupt any blocking system calls. */ | ||
| 3390 | signal_quit (); | ||
| 3391 | } | ||
| 3392 | } | ||
| 3393 | |||
| 3394 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | ||
| 3395 | } | ||
| 3396 | |||
| 3397 | /* Main message dispatch loop. */ | 3358 | /* Main message dispatch loop. */ |
| 3398 | 3359 | ||
| 3399 | static void | 3360 | static void |
| @@ -3411,6 +3372,9 @@ w32_msg_pump (deferred_msg * msg_buf) | |||
| 3411 | { | 3372 | { |
| 3412 | switch (msg.message) | 3373 | switch (msg.message) |
| 3413 | { | 3374 | { |
| 3375 | case WM_NULL: | ||
| 3376 | /* Produced by complete_deferred_msg; just ignore. */ | ||
| 3377 | break; | ||
| 3414 | case WM_EMACS_CREATEWINDOW: | 3378 | case WM_EMACS_CREATEWINDOW: |
| 3415 | w32_createwindow ((struct frame *) msg.wParam); | 3379 | w32_createwindow ((struct frame *) msg.wParam); |
| 3416 | if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0)) | 3380 | if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0)) |
| @@ -3560,7 +3524,8 @@ complete_deferred_msg (HWND hwnd, UINT msg, LRESULT result) | |||
| 3560 | deferred_msg * msg_buf = find_deferred_msg (hwnd, msg); | 3524 | deferred_msg * msg_buf = find_deferred_msg (hwnd, msg); |
| 3561 | 3525 | ||
| 3562 | if (msg_buf == NULL) | 3526 | if (msg_buf == NULL) |
| 3563 | abort (); | 3527 | /* Message may have been cancelled, so don't abort(). */ |
| 3528 | return; | ||
| 3564 | 3529 | ||
| 3565 | msg_buf->result = result; | 3530 | msg_buf->result = result; |
| 3566 | msg_buf->completed = 1; | 3531 | msg_buf->completed = 1; |
| @@ -3569,6 +3534,26 @@ complete_deferred_msg (HWND hwnd, UINT msg, LRESULT result) | |||
| 3569 | PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0); | 3534 | PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0); |
| 3570 | } | 3535 | } |
| 3571 | 3536 | ||
| 3537 | void | ||
| 3538 | cancel_all_deferred_msgs () | ||
| 3539 | { | ||
| 3540 | deferred_msg * item; | ||
| 3541 | |||
| 3542 | /* Don't actually need synchronization for read access, since | ||
| 3543 | modification of single pointer is always atomic. */ | ||
| 3544 | /* enter_crit (); */ | ||
| 3545 | |||
| 3546 | for (item = deferred_msg_head; item != NULL; item = item->next) | ||
| 3547 | { | ||
| 3548 | item->result = 0; | ||
| 3549 | item->completed = 1; | ||
| 3550 | } | ||
| 3551 | |||
| 3552 | /* leave_crit (); */ | ||
| 3553 | |||
| 3554 | /* Ensure input thread is woken so it notices the completion. */ | ||
| 3555 | PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0); | ||
| 3556 | } | ||
| 3572 | 3557 | ||
| 3573 | DWORD | 3558 | DWORD |
| 3574 | w32_msg_worker (dw) | 3559 | w32_msg_worker (dw) |
| @@ -3595,6 +3580,66 @@ w32_msg_worker (dw) | |||
| 3595 | return 0; | 3580 | return 0; |
| 3596 | } | 3581 | } |
| 3597 | 3582 | ||
| 3583 | static void | ||
| 3584 | post_character_message (hwnd, msg, wParam, lParam, modifiers) | ||
| 3585 | HWND hwnd; | ||
| 3586 | UINT msg; | ||
| 3587 | WPARAM wParam; | ||
| 3588 | LPARAM lParam; | ||
| 3589 | DWORD modifiers; | ||
| 3590 | |||
| 3591 | { | ||
| 3592 | W32Msg wmsg; | ||
| 3593 | |||
| 3594 | wmsg.dwModifiers = modifiers; | ||
| 3595 | |||
| 3596 | /* Detect quit_char and set quit-flag directly. Note that we | ||
| 3597 | still need to post a message to ensure the main thread will be | ||
| 3598 | woken up if blocked in sys_select(), but we do NOT want to post | ||
| 3599 | the quit_char message itself (because it will usually be as if | ||
| 3600 | the user had typed quit_char twice). Instead, we post a dummy | ||
| 3601 | message that has no particular effect. */ | ||
| 3602 | { | ||
| 3603 | int c = wParam; | ||
| 3604 | if (isalpha (c) && wmsg.dwModifiers == ctrl_modifier) | ||
| 3605 | c = make_ctrl_char (c) & 0377; | ||
| 3606 | if (c == quit_char) | ||
| 3607 | { | ||
| 3608 | Vquit_flag = Qt; | ||
| 3609 | |||
| 3610 | /* The choice of message is somewhat arbitrary, as long as | ||
| 3611 | the main thread handler just ignores it. */ | ||
| 3612 | msg = WM_NULL; | ||
| 3613 | |||
| 3614 | /* Interrupt any blocking system calls. */ | ||
| 3615 | signal_quit (); | ||
| 3616 | |||
| 3617 | /* As a safety precaution, forcibly complete any deferred | ||
| 3618 | messages. This is a kludge, but I don't see any particularly | ||
| 3619 | clean way to handle the situation where a deferred message is | ||
| 3620 | "dropped" in the lisp thread, and will thus never be | ||
| 3621 | completed, eg. by the user trying to activate the menubar | ||
| 3622 | when the lisp thread is busy, and then typing C-g when the | ||
| 3623 | menubar doesn't open promptly (with the result that the | ||
| 3624 | menubar never responds at all because the deferred | ||
| 3625 | WM_INITMENU message is never completed). Another problem | ||
| 3626 | situation is when the lisp thread calls SendMessage (to send | ||
| 3627 | a window manager command) when a message has been deferred; | ||
| 3628 | the lisp thread gets blocked indefinitely waiting for the | ||
| 3629 | deferred message to be completed, which itself is waiting for | ||
| 3630 | the lisp thread to respond. | ||
| 3631 | |||
| 3632 | Note that we don't want to block the input thread waiting for | ||
| 3633 | a reponse from the lisp thread (although that would at least | ||
| 3634 | solve the deadlock problem above), because we want to be able | ||
| 3635 | to receive C-g to interrupt the lisp thread. */ | ||
| 3636 | cancel_all_deferred_msgs (); | ||
| 3637 | } | ||
| 3638 | } | ||
| 3639 | |||
| 3640 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | ||
| 3641 | } | ||
| 3642 | |||
| 3598 | /* Main window procedure */ | 3643 | /* Main window procedure */ |
| 3599 | 3644 | ||
| 3600 | LRESULT CALLBACK | 3645 | LRESULT CALLBACK |
| @@ -6524,7 +6569,7 @@ If optional parameter FRAME is not specified, use selected frame.") | |||
| 6524 | 6569 | ||
| 6525 | CHECK_NUMBER (command, 0); | 6570 | CHECK_NUMBER (command, 0); |
| 6526 | 6571 | ||
| 6527 | PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, XINT (command), 0); | 6572 | SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, XINT (command), 0); |
| 6528 | 6573 | ||
| 6529 | return Qnil; | 6574 | return Qnil; |
| 6530 | } | 6575 | } |
| @@ -6700,13 +6745,13 @@ DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key, Sw32_reconstruct_hot | |||
| 6700 | 6745 | ||
| 6701 | key = Fcons (key, Qnil); | 6746 | key = Fcons (key, Qnil); |
| 6702 | if (w32_modifiers & MOD_SHIFT) | 6747 | if (w32_modifiers & MOD_SHIFT) |
| 6703 | key = Fcons (intern ("shift"), key); | 6748 | key = Fcons (Qshift, key); |
| 6704 | if (w32_modifiers & MOD_CONTROL) | 6749 | if (w32_modifiers & MOD_CONTROL) |
| 6705 | key = Fcons (intern ("control"), key); | 6750 | key = Fcons (Qctrl, key); |
| 6706 | if (w32_modifiers & MOD_ALT) | 6751 | if (w32_modifiers & MOD_ALT) |
| 6707 | key = Fcons (intern (NILP (Vw32_alt_is_meta) ? "alt" : "meta"), key); | 6752 | key = Fcons (NILP (Vw32_alt_is_meta) ? Qalt : Qmeta, key); |
| 6708 | if (w32_modifiers & MOD_WIN) | 6753 | if (w32_modifiers & MOD_WIN) |
| 6709 | key = Fcons (intern ("hyper"), key); | 6754 | key = Fcons (Qhyper, key); |
| 6710 | 6755 | ||
| 6711 | return key; | 6756 | return key; |
| 6712 | } | 6757 | } |