New issue
Advanced search Search tips

Issue 890016 link

Starred by 1 user

Issue metadata

Status: Assigned
Owner:
Cc:
EstimatedDays: ----
NextAction: ----
OS: Windows
Pri: 2
Type: Bug

Blocked on:
issue 888559



Sign in to add a comment

MessagePumpForUI (Win) : Unwinding multiple layers of nested system loops can starve application tasks

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

Issue description

Chrome Version : beginning of time?!

The following code will never return :

  void SubPumpFunc(OnceClosure on_done) {
    MessageLoopCurrent::ScopedNestableTaskAllower allow_nestable_tasks;
    MSG msg;
    while (::GetMessage(&msg, NULL, 0, 0)) {
      ::TranslateMessage(&msg);
      ::DispatchMessage(&msg);
    }
    std::move(on_done).Run();
  }

  void Test() {
    MessageLoop message_loop(MessageLoop::TYPE_UI);

    RunLoop run_loop;

    // Enter multiple levels of nested subpumps.
    message_loop.task_runner()->PostTask(
        FROM_HERE, BindOnce(&SubPumpFunc, run_loop.QuitClosure()));
    message_loop.task_runner()->PostTask(
        FROM_HERE, BindOnce(&SubPumpFunc, DoNothing::Once()));

    // Quit the subsubpump (extra tasks ensure enough cycles to fully handle).
    message_loop.task_runner()->PostTask(FROM_HERE,
                                         BindOnce(&::PostQuitMessage, 0));
    message_loop.task_runner()->PostTask(FROM_HERE, DoNothing());
    message_loop.task_runner()->PostTask(FROM_HERE, DoNothing());


    // Quit the subpump.
    message_loop.task_runner()->PostTask(FROM_HERE,
                                         BindOnce(&::PostQuitMessage, 0));

    run_loop.Run();
  }

the reason is that the first quit eats the kMsgHaveWork message when it reposts the WM_QUIT (ref. https://chromium-review.googlesource.com/c/chromium/src/+/1240158). As such, the subpump is no longer processing application tasks when it un-nests (and hence fails to post the second quit).

This was worse before https://chromium-review.googlesource.com/c/chromium/src/+/1240158 (the first quit would be taken away from either subpump and we would stay stuck forever); now at least the quits are handled, it's just that application tasks may be starved on resume if there were multiple layers of nesting subpumps.
 
Project Member

Comment 1 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

Sign in to add a comment