Fix nested message loop handling
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Oxide |
Fix Released
|
Medium
|
Chris Coulson |
Bug Description
I've reviewed the behaviour of Oxide if Qt or an application executes a nested QEventLoop on the main thread. This is needed to ensure we can safely handle drag and drop:
- Scenario 1: QEventLoop executed with no Chromium code on the stack.
In this case, the nested loop will pump the Chromium event queue as normal, and this is fine because there are no nested Chromium tasks.
- Scenario 2: QEventLoop executed from a non-nested Chromium task.
In this case, the nested loop will pump the Chromium event queue by re-entering oxide::
- It doesn't look like there's any re-entrancy issues here.
- MessageLoop:
- MessageLoop:
- MessageLoop:
The last point seems like an edge case - tasks are only added to this work queue via nested calls to DoWork() and DoDelayedWork() when nestable tasks are allowed but the task isn't nestable. We don't do this anywhere in Oxide, although that doesn't mean it couldn't happen elsewhere in Chromium.
- Scenario 3: QEventLoop executed from a nested Chromium task (via RunLoop::Run)
As 2, above. Nested tasks are still blocked in DoIdle() and DoDelayedWork() because RunTask clears MessageLoop:
- Scenario 4: QEventLoop executed from a non-nested Chromium task with nestable tasks enabled (via MessageLoop:
In this case, the nested loop will pump the Chromium event queue by re-entering oxide::
- MessageLoop:
- MessageLoop:
- MessageLoop:
- Scenario 5: QEventLoop executed from a nested Chromium task (via RunLoop::Run) with nestable tasks enabled (via MessageLoop:
- MessageLoop:
- MessageLoop:
- MessageLoop:
It seems like we should detect re-entrancy from a nested QEventLoop in oxide::
- If we re-enter from a nested QEventLoop, the extra bit on the current RunState will be set. In this case, we should create a new RunLoop instance before calling in to MessageLoop.
- A nested RunLoop creates a new RunState in our MessagePump. In this case, we won't trigger the re-entrancy detection (and we don't need to because we already have the correct RunLoop depth)
After this is fixed, a nested QEventLoop created outside of Oxide will process Qt events but won't run any Oxide or Chromium tasks unless the call out of Oxide enables nestable tasks with MessageLoop:
Looking at the broken cases above:
- MessageLoop:
- In scenario 4 (which will most likely happen with drag and drop), MessageLoop:
Related branches
Changed in oxide: | |
importance: | Undecided → Medium |
status: | New → Triaged |
description: | updated |
description: | updated |
Changed in oxide: | |
assignee: | nobody → Chris Coulson (chrisccoulson) |
milestone: | none → branch-1.13 |
status: | Triaged → Fix Released |