Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't run python-libjuju async loop on background thread in py3.8, py3.9 and py3.10? due to "set_wakeup_fd() only works in main thread" #1010

Closed
ajkavanagh opened this issue Jan 23, 2024 · 0 comments · Fixed by #1014

Comments

@ajkavanagh
Copy link

Description

For zaza, for various reasons, we need/have to run python-libjuju's async loop in a background thread. This is because the zaza is written as a non-blocking test framework on top of unitest. However, the async thread needs to keep running to get status updates and so to make it all work, python-libjuju runs on the background thread.

However, due to python/cpython#87173 and a recent-ish change this now blows up on py3.8, py3.9 and py3.10. This is a major problem for our CI as it runs py3.8 test runners (a limitation we do eventually need to solve).

The traceback is here:

   File "/home/runner/work/zaza/zaza/.tox/func-target/lib/python3.10/site-packages/juju/controller.py", line 108, in connect
     await self._connector.connect_controller(controller_name, **kwargs)
   File "/home/runner/work/zaza/zaza/.tox/func-target/lib/python3.10/site-packages/juju/client/connector.py", line 127, in connect_controller
     await self.connect(
   File "/home/runner/work/zaza/zaza/.tox/func-target/lib/python3.10/site-packages/juju/client/connector.py", line 86, in connect
     self._connection = await Connection.connect(**kwargs)
   File "/home/runner/work/zaza/zaza/.tox/func-target/lib/python3.10/site-packages/juju/client/connection.py", line 356, in connect
     await self._connect_with_redirect([_ep])
   File "/home/runner/work/zaza/zaza/.tox/func-target/lib/python3.10/site-packages/juju/client/connection.py", line 908, in _connect_with_redirect
     login_result = await self._connect_with_login(endpoints)
   File "/home/runner/work/zaza/zaza/.tox/func-target/lib/python3.10/site-packages/juju/client/connection.py", line 875, in _connect_with_login
     await self._connect(endpoints)
   File "/home/runner/work/zaza/zaza/.tox/func-target/lib/python3.10/site-packages/juju/client/connection.py", line 824, in _connect
     result = await task
   File "/usr/lib/python3.10/asyncio/tasks.py", line 571, in _wait_for_one
     return f.result()  # May raise f.exception().
   File "/home/runner/work/zaza/zaza/.tox/func-target/lib/python3.10/site-packages/juju/client/connection.py", line 813, in _try_endpoint
     return await self._open(endpoint, cacert)
   File "/home/runner/work/zaza/zaza/.tox/func-target/lib/python3.10/site-packages/juju/client/connection.py", line 430, in _open
     loop.add_signal_handler(sig, _exit_tasks)
   File "/usr/lib/python3.10/asyncio/unix_events.py", line 107, in add_signal_handler
     raise RuntimeError(str(exc))
 RuntimeError: set_wakeup_fd only works in main thread of the main interpreter
 func-target: exit 1 (0.70 seconds) /home/runner/work/zaza/zaza> functest-run-suite --keep-model --bundle first pid=11317
.pkg: _exit> python /home/runner/.local/lib/python3.10/site-packages/pyproject_api/_backend.py True setuptools.build_meta __legacy__
 func-target: FAIL code 1 (26.05=setup[24.57]+cmd[0.78,0.70] seconds)
 evaluation failed :( (26.13 seconds)
Error: Process completed with exit code 1.

The easiest fix is probably to wrap the code in the same way as in juju/jasyncio.py:

    added = False
    try:
        loop.add_signal_handler(signal.SIGINT, abort)
        added = True
    except (ValueError, OSError, RuntimeError) as e:
        # add_signal_handler doesn't work in a thread
        if 'main thread' not in str(e):
            raise

Urgency

Annoying bug in our test suite

Python-libjuju version

=3.2.2

Juju version

3.1

Reproduce / Test

A bit tricky for a reproducer; zaza runs libjuju in a background thread here: https://github.com/openstack-charmers/zaza/blob/master/zaza/__init__.py
@ajkavanagh ajkavanagh added the bug label Jan 23, 2024
@cderici cderici added the 3.x label Jan 24, 2024
cderici added a commit to cderici/python-libjuju that referenced this issue Jan 25, 2024
1. Because if someone runs pylibjuju in an off-main thread, then
add_signal_handler will (rightfully) complain (see issue juju#1010).

2. Pylibjuju as a library shouldn't enforce a certain way of handling
signals. Clients should install their handlers however they wanna
handle them.

Fixes juju#1010
jujubot added a commit that referenced this issue Jan 29, 2024
#1014

#### Description

In #1010 it's reported that running pylibjuju in an off-main thread blows up the `add_signal_handler` (for a good reason). Also per the discussion in the #1011 about signal handlers, this PR removes the code that installs signal handlers to the event loop at the connection creation. See [my comment](#1011 (comment)) in #1011 for details about reasoning.

Fixes #1010
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants