beeware / beeware/toga

Android event loop is not thread-safe

Open
#2,138 1 comment 0 reactions 0 assignees View on GitHub
android bug
Dominant language
Python
Stars
5.4k
Forks
827
Avg merge
9h 45m
Merged PRs (30d)
58

Description

In https://github.com/beeware/toga/pull/1706, we made Toga use `call_soon_threadsafe` when adding tasks from another thread. However, it doesn't look like the current Android implementation is actually thread-safe.

In the base class in `asyncio.base_events`, the implementations of `call_soon` and `call_soon_threadsafe` are virtually identical. Both of them call `_call_soon`, which is itself thread-safe because all it does is add the task to a deque. The only difference is that `call_soon_threadsafe` then writes something to a pipe to wake up the event loop.

However, the Android event loop overrides `_call_soon` to call `enqueue_android_wakeup_for_delayed_tasks`, which calls `_get_next_delayed_task_wakeup`, which iterates and modifies many data structures in a way that can't possibly be safe to do outside of the event loop's own thread.

The simplest solution I can think of is to move the call of `_get_next_delayed_task_wakeup` into `run_delayed_tasks`, which always runs on the event loop's own thread, and then pass the result as an argument to `enqueue_android_wakeup_for_delayed_tasks`. In the case of `_call_soon`, that argument would always be zero.

* Related: #2179

Contributor guide

Open the contributing guide

Research direction

Start by reading asyncio.base_events and the Android event-loop overrides of _call_soon, run_delayed_tasks, enqueue_android_wakeup_for_delayed_tasks, and _get_next_delayed_task_wakeup. Trace how call_soon_threadsafe behaves from another thread. Done means delayed-task wakeup bookkeeping runs safely on the event-loop thread while both scheduling paths continue to wake the loop correctly.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, python
Domain
mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.