New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 888559 link

Starred by 1 user

Issue metadata

Status: Fixed
Owner:
Closed: Oct 3
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Windows
Pri: 1
Type: Bug

Blocking:
issue 863341
issue 885371
issue 890016



Sign in to add a comment

MessagePumpForUI (Win) can steal WM_QUIT from a nested native loop

Project Member Reported by gab@chromium.org, Sep 24

Issue description

Chrome Version: 68.0.3409.0+ (r553653)
OS: Windows

The following sequence of native events can cause MessageLoopForUI to
steal WM_QUIT from a nested native::GetMessage() loop :
[kMsgHaveWork, WM_QUIT, ...].

This was because kMsgHaveWork results in:
  MessagePumpForUI::MessageCallback
  => MessagePumpForUI::HandleWorkMessage
  => MessagePumpForUI::ProcessPumpReplacementMessage
which steals the upcoming WM_QUIT from the native queue
  => MessagePumpForUI::ProcessMessageHelper(WM_QUIT)
which ignores WM_QUIT by default.

WM_QUIT has been ignored as of crrev.com/553653 (to solve other issues)
Introducing this bug.

Then it was selectively unconditionally re-enabled for printing in
crrev.com/573620. Printing's issue might have been this very issue
but the fix also results in quitting the underlying RunLoop::Run().
I'm not sure that's necessary for printing but I plan to keep that
behavior in the initial fix to avoid changing too much at once.

This was caught as a failure on https://chromium-review.googlesource.com/c/chromium/src/+/1232518/1
which changes the order in which MessageLoop work is processed in
a way that shouldn't matter but broke RunTest_PostDelayedTask_SharedTimer_SubPump().

It might also be the reason for some failures on alexclarke's incoming change to put SequenceManager on top of MessageLoop on BrowserThread::UI (and thus similarly changing MessageLoop work order in a way that shouldn't matter -- crbug.com/863341)

Incoming fix @ https://chromium-review.googlesource.com/c/chromium/src/+/1240158
 
Blocking: 863341 885371
Cc: alexclarke@chromium.org
Description: Show this description
Re crrev.com/573620, I think the issue there was that WM_QUIT is the expected quit signal (graceful teardown, equivalent to SIGTERM) in that case.


Re. #3, right, but it has a 50/50 chance that the WM_QUIT is caught by the nested ::GetMessage() loop and then wouldn't result in quitting the RunLoop anyways... Unless it wasn't inside a ::GetMessage() loop (in which case reposting the WM_QUIT was irrelevant).

So at least one portion of that change was not necessary.

If reposting to the native subpump is the necessary bit, then my change fixes that too and we can remove EnableWmQuit().

If handling WM_QUIT like a QuitClosure() from the main RunLoop is the necessary bit (and there isn't a native ::GetMessage() loop), then we need to keep EnableWmQuit() (as my CL currently does).
The problem is that no printing tests were added in that CL, so I have no way to tell if keeping EnableWmQuit() is necessary...
EnableWmQuit() is likely still necessary. Would it help if I wrote a test now?
Yes it would, thanks
Sure, I got a test. Will clean it up and send it out soon.
Blocking: 890016
Project Member

Comment 10 by bugdroid1@chromium.org, Sep 28

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/6b9a2faf89e9b67fb6cb8d0986c431923f757b98

commit 6b9a2faf89e9b67fb6cb8d0986c431923f757b98
Author: Gabriel Charette <gab@chromium.org>
Date: Fri Sep 28 21:14:29 2018

Ensure that WM_QUIT is visible to nested ::GetMessage() loops.

When a kMsgHaveWork task is processed by the pump, allowing it a
timeslice in which to process tasks, we pull the next MSG from the
thread's queue and dispatch that, to minimize impact of kMsgHaveWork on
MSG scheduling. WM_QUIT must be observed directly by GetMessage in order
for a nested loop to exit, though, so we must re-post it to the thread
queue, for GetMessage to report.

Re-posting was removed by crrev.com/553653, which caused WM_QUIT to be
ignored by MessagePumpForUI, missing that we must still re-post the
message, in case we're inside a nested loop, to allow it to quit.

To address this:
- When pulling a MSG to replace kMsgHaveWork, we unconditionally re-post
  WM_QUIT messages, in case ::GetMessage() needs to see them.
- Only actually handle WM_QUIT when it is observed directly by
  DoRunLoop(), i.e. if WM_QUIT was the kMsgHaveWork replacement, don't
  process it until we see it re-posted.
- Continue ignoring WM_QUIT when handled iff |!enable_wm_quit_| to
  properties of crrev.com/573620.
- Add comments and tests to properly explain and verify the special-case
  handling of WM_QUIT.
- Document a another edge case bug uncovered by this investigation.

Bug:  888559 , 890016
Change-Id: I548165b6103b1c7454f90335ba6dfb4f8cf149d9
Reviewed-on: https://chromium-review.googlesource.com/1240158
Commit-Queue: Gabriel Charette <gab@chromium.org>
Reviewed-by: Wez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#595217}
[modify] https://crrev.com/6b9a2faf89e9b67fb6cb8d0986c431923f757b98/base/message_loop/message_loop_unittest.cc
[modify] https://crrev.com/6b9a2faf89e9b67fb6cb8d0986c431923f757b98/base/message_loop/message_pump_win.cc

Status: Fixed (was: Assigned)

Sign in to add a comment