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

Segmentation fault when exiting multi-threaded program #250

Closed
freakboy3742 opened this issue Jan 18, 2023 · 0 comments · Fixed by #246
Closed

Segmentation fault when exiting multi-threaded program #250

freakboy3742 opened this issue Jan 18, 2023 · 0 comments · Fixed by #246
Labels
bug A crash or error in behavior.

Comments

@freakboy3742
Copy link
Member

freakboy3742 commented Jan 18, 2023

Describe the bug

When running multiple threads, Rubicon will occasionally raise a segfault on exit.

This has been observed in the newly added Toga GUI testbed; ~1 in 10 runs will exit with a segfault

Steps to reproduce

Run the Toga GUI test case on macOS or iOS (currently in the macos-probe branch). It may take multiple runs for the problem to manifest.

Expected behavior

No crash on exit.

Screenshots

No response

Environment

  • Operating System: macOS 12.5.1, iOS 16.2
  • Python version: 3.10
  • Software versions:
    • Briefcase: 0.3.12-dev @ 40fccb137
    • Toga: 0.3.0dev39+ (macos-probe branch)

However, I have no reason to believe the problem is specific to these versions.

Logs

The error seen occurs at shutdown of the test suite.

Fatal Python error: Segmentation fault

Thread 0x00000001707ab000 (most recent call first):
  File "/Users/rkm/beeware/rubicon/objc/src/rubicon/objc/eventloop.py", line 312 in cancel
  File "/Users/rkm/beeware/rubicon/objc/src/rubicon/objc/eventloop.py", line 284 in disable_read
  File "/Users/rkm/beeware/rubicon/objc/src/rubicon/objc/eventloop.py", line 364 in _remove_reader
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/selector_events.py", line 94 in _close_self_pipe
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/selector_events.py", line 87 in close
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/unix_events.py", line 68 in close
  File "/Users/rkm/beeware/rubicon/objc/src/rubicon/objc/eventloop.py", line 619 in close
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/pytest_asyncio/plugin.py", line 386 in pytest_fixture_post_finalizer
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/pluggy/_callers.py", line 39 in _multicall
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/pluggy/_manager.py", line 80 in _hookexec
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/pluggy/_hooks.py", line 265 in __call__
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/_pytest/fixtures.py", line 1039 in finish
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/_pytest/fixtures.py", line 684 in <lambda>
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/_pytest/runner.py", line 523 in teardown_exact
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/_pytest/runner.py", line 180 in pytest_runtest_teardown
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/pluggy/_callers.py", line 39 in _multicall
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/pluggy/_manager.py", line 80 in _hookexec
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/pluggy/_hooks.py", line 265 in __call__
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/_pytest/runner.py", line 260 in <lambda>
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/_pytest/runner.py", line 339 in from_call
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/_pytest/runner.py", line 259 in call_runtest_hook
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/_pytest/runner.py", line 220 in call_and_report
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/_pytest/runner.py", line 132 in runtestprotocol
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/_pytest/runner.py", line 112 in pytest_runtest_protocol
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/pluggy/_callers.py", line 39 in _multicall
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/pluggy/_manager.py", line 80 in _hookexec
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/pluggy/_hooks.py", line 265 in __call__
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/_pytest/main.py", line 349 in pytest_runtestloop
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/pluggy/_callers.py", line 39 in _multicall
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/pluggy/_manager.py", line 80 in _hookexec
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/pluggy/_hooks.py", line 265 in __call__
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/_pytest/main.py", line 324 in _main
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/_pytest/main.py", line 270 in wrap_session
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/_pytest/main.py", line 317 in pytest_cmdline_main
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/pluggy/_callers.py", line 39 in _multicall
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/pluggy/_manager.py", line 80 in _hookexec
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/pluggy/_hooks.py", line 265 in __call__
  File "/Users/rkm/beeware/toga/venv3.10/lib/python3.10/site-packages/_pytest/config/__init__.py", line 167 in main
  File "/Users/rkm/beeware/toga/testbed/tests/testbed.py", line 24 in run_tests
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 953 in run
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 1016 in _bootstrap_inner
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 973 in _bootstrap

Current thread 0x0000000100c2c580 (most recent call first):
  File "/Users/rkm/beeware/rubicon/objc/src/rubicon/objc/runtime.py", line 836 in send_message
  File "/Users/rkm/beeware/rubicon/objc/src/rubicon/objc/api.py", line 212 in __call__
  File "/Users/rkm/beeware/rubicon/objc/src/rubicon/objc/api.py", line 290 in __call__
  File "/Users/rkm/beeware/rubicon/objc/src/rubicon/objc/eventloop.py", line 737 in start
  File "/Users/rkm/beeware/rubicon/objc/src/rubicon/objc/eventloop.py", line 441 in run
  File "/Users/rkm/beeware/rubicon/objc/src/rubicon/objc/eventloop.py", line 489 in run_forever
  File "/Users/rkm/beeware/toga/cocoa/src/toga_cocoa/app.py", line 341 in main_loop
  File "/Users/rkm/beeware/toga/core/src/toga/app.py", line 551 in main_loop
  File "/Users/rkm/beeware/toga/testbed/tests/testbed.py", line 128 in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py", line 86 in _run_code
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py", line 96 in _run_module_code
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py", line 224 in run_module
  File "<string>", line 1 in <module>

Additional context

Discovered while testing beeware/toga#1707.

The Toga GUI testbed uses pytest-asyncio; this appears to be the root of the problem.

pytest-asyncio generates an event loop for each thread. The testbed uses the secondary thread to drive the test suite, and the main thread is used to run the application. The event loop on the secondary thread injects co-routines into the main thread to build fixtures, and to run the tests.

On shutdown, both event loops are closed. Each event loop has a "self pipe" which is used to wake up the event loop when a co-routine is added to a dormant event loop; it is closing this "self pipe" that raises the segfault.

The issue appears to be that in a multi-threaded case, depending on the exact sequence of events either the CFRunLoop or the socket itself passes out of scope before one of the threads is able to close the self-pipe.

@freakboy3742 freakboy3742 added the bug A crash or error in behavior. label Jan 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A crash or error in behavior.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant