Comment 0 for bug 1536797

Revision history for this message
Chris Coulson (chrisccoulson) wrote :

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::qt::MessagePump::RunOneTask()
  - It doesn't look like there's any re-entrancy issues here.
  - MessageLoop::DoWork() will not run any tasks because the MessageLoop is in a task and nestable tasks haven't been explicitly allowed (MessageLoop::nestable_tasks_allowed_ is set to false in RunTask).
  - MessageLoop::DoDelayedWork() - same as DoWork()
  - MessageLoop::DoIdleWork() will process tasks from the deferred non-nestable work queue.

The last point is a bug, as DoIdleWork() should not run tasks in a nested loop. However, it 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 nestable_tasks_allowed_ before running the nested task. However, DoIdleWork will behave correctly here because the RunLoop::run_depth_ check in MessageLoop::ProcessNextDelayedNonNestableTask will work.

It seems like we should detect re-entrancy from a nested QEventLoop in oxide::qt::MessagePump::RunOneTask(). We could do this by adding an extra bit to RunState, that we set when calling in to MessageLoop.
- 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)