question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

RuntimeError when showing dialog from async handler in Cocoa

See original GitHub issue

Describe the bug A runtime error “Cannot enter into task while another task is being executed” is raised when showing a dialog from an async callback. This only occurs when there is already a “background task” running, either scheduled manually with asyncio.create_task or through toga with toga.App.add_background_task. The background task then crashes.

To Reproduce

Example code to reproduce, adapted from the handlers example:

Example

import asyncio

import toga
from toga.constants import COLUMN
from toga.style import Pack


class HandlerApp(toga.App):

    async def do_async(self, widget, **kwargs):

        widget.enabled = False
        for i in range(1, 10):
            self.async_label.text = "Iteration {}".format(i)
            if not self.ask_to_continue():
                break

        self.async_label.text = "Ready."
        widget.enabled = True

    def ask_to_continue(self):
        return self.main_window.confirm_dialog('Continue?', 'Press OK to continue.')

    async def do_background_task(self, widget, **kwargs):
        while True:
            self.counter += 1
            self.label.text = "Background: Iteration {}".format(self.counter)
            await asyncio.sleep(1)

    def startup(self):
        self.main_window = toga.MainWindow(title=self.name)

        self.label = toga.Label('Ready.', style=Pack(padding=10))
        self.async_label = toga.Label('Ready.', style=Pack(padding=10))

        self.counter = 0
        self.add_background_task(self.do_background_task)

        btn_style = Pack(flex=1)
        btn_async = toga.Button('Async callback', on_press=self.do_async, style=btn_style)

        box = toga.Box(
            children=[
                self.label,
                btn_async,
                self.async_label,
            ],
            style=Pack(
                flex=1,
                direction=COLUMN,
                padding=10
            )
        )

        self.main_window.content = box
        self.main_window.show()


def main():
    return HandlerApp('Handlers', 'org.beeware.handlers')


if __name__ == '__main__':
    app = main()
    app.main_loop()

This raises the exception:

Exception ignored on calling ctypes callback function: <function CFTimerHandle._cf_timer_callback.<locals>.cf_timer_callback at 0x114c4e670>
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/rubicon/objc/eventloop.py", line 155, in cf_timer_callback
    callback(*args)
  File "/usr/local/lib/python3.8/site-packages/rubicon/objc/eventloop.py", line 304, in _callback
    context.run(callback, *args)
RuntimeError: Cannot enter into task <Task pending name='Task-1' coro=<handler_with_cleanup() running at /usr/local/lib/python3.8/site-packages/toga/handlers.py:25> wait_for=<Future finished result=None>> while another task <Task pending name='Task-2' coro=<handler_with_cleanup() running at /usr/local/lib/python3.8/site-packages/toga/handlers.py:25>> is being executed.

Expected behavior The background task should pause while the dialog is blocking the event loop and resume afterwards.

Environment:

  • Operating System: macOS Catalina, macOS Big Sur
  • Python version: 3.8.5
  • Software versions:
    • Toga: 0.3.0.dev23

Additional context This may be an issue with the Cocoa event loop integration in rubicon.objc.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:11 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
massenzcommented, Mar 28, 2021

In addition, toga’s asyncio integration is barely documented.

“barely documented” seems even an exaggeration: the “reference” doc for add_background_task(handler) won’t even specify the signature of handler, so much so that I have to reverse engineer it 😃

(incidentally, AFAICT, it gets invoked with two “app variants”? my main class (a toga.App) and a toga_iOS.app.App?)

0reactions
kakos-k9commented, Jan 27, 2022

I would like to know how you did to call another screen, could you show the code?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why does the async/await code to show my ContentDialog ...
So I changed the code to this, adding "async" to the method/event handler and "await" to the call to show the content dialog:...
Read more >
Xcode 14 Release Notes | Apple Developer Documentation
Fixed: Objective-C documentation for multi-language APIs show Swift symbol relationships instead of Objective-C relationships. (91627374).
Read more >
Changelog — Python 3.11.1 documentation
gh-65802: Document handling of extensions in Save As dialogs. ... RuntimeError: Event loop is closed on interpreter exit after asynchronous socket activity.
Read more >
Changes in Data Abstract for Cocoa
No changes for Data Abstract for Cocoa, in this release ... if schema fails to download in SQL Explorer; show error icon &...
Read more >
更新日志 — Python 3.7.6 文档
Calling the previous signal handler in faulthandler signal handler uses more ... bpo-37929: IDLE Settings dialog now closes properly when there is no...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found