-
Notifications
You must be signed in to change notification settings - Fork 656
Description
Describe the bug
Software Incident Report
Report ID: SR-202512-PY313-01
Status: Open / Critical
Date: December 29, 2025, 00:12:24 AM IST
-
Executive Summary
A fatal runtime crash was observed in the Python 3.13 application. The process terminated via an EXC_BAD_INSTRUCTION (SIGILL) signal triggered by a threading assertion failure within the macOS system libraries. The crash occurs because a background worker thread attempted to invoke a system API (TSMGetInputSourceProperty) that macOS requires to be executed strictly on the Main Thread. -
System Information
Process: Python [8137]
Path: /Library/Frameworks/Python.framework/Versions/3.13/Resources/Python.app/Contents/MacOS/Python
Python Version: 3.13.7 (Native X86-64)
OS Version: macOS 10.15.7 (Build 19H2026)
System Integrity Protection: Enabled
Uptime: 25,000 seconds (~7 hours)
- Failure Analysis
3.1 Crash Signature
Crashed Thread: 8
Exception Type: EXC_BAD_INSTRUCTION (SIGILL)
Termination Reason: Namespace SIGNAL, Code 0x4
Specific Error: BUG IN CLIENT OF LIBDISPATCH: Assertion failed: Block was expected to execute on queue [com.apple.main-thread]
3.2 Root Cause Identification
Review of the stack trace for Thread 8 identifies the exact sequence of the failure:
Thread 8 (a background thread) is running a Python generator (gen_iternext).
The generator calls a C-extension function via _ctypes.cpython-313-darwin.so.
The ctypes call invokes TSMGetInputSourceProperty within the Apple HIToolbox framework.
The macOS Grand Central Dispatch (libdispatch) detects that this system property query is happening on a background queue.
To prevent system instability, libdispatch triggers a hardware-level exception (_dispatch_assert_queue_fail), crashing the app.
3.3 Thread 0 (Main Thread) Context
The log shows the Main Thread was occupied with the Tkinter event loop (_tkinter_tkapp_mainloop_impl) and Tcl callbacks. This confirms that the application is a GUI-based program where the Main Thread is dedicated to rendering and event handling, while the logic in Thread 8 was attempting "illegal" direct system access.
- Impact
Immediate Crash: The application terminates instantly without any opportunity for Python-level error handling (try/except).
Data Loss: Any unsaved state in memory is lost as the process is killed by the OS kernel.
- Corrective Action Plan
Action 1: Refactor Background Queries
Any code utilizing ctypes or libraries that query keyboard layouts (e.g., pynput, pyautogui, or custom HIToolbox wrappers) must be moved out of the background thread.
Action 2: Thread-Safe Delegation
Use the queue module or Tkinter's .after() method to delegate the system query to the main thread.
Current (Faulty): Thread 8 -> ctypes -> HIToolbox
Proposed (Stable): Thread 8 -> queue.put(request) -> Main Thread (Thread 0) -> HIToolbox -> queue.put(result)
Action 3: Library Audit
Since this is occurring on Python 3.13.7, ensure all third-party binaries (located in site-packages) are compatible with 3.13's new internal threading structures.
- Conclusion
The crash is a definitive Thread Safety Violation. The application is attempting to query macOS input settings from a worker thread, which is strictly prohibited by the OS. Synchronizing these calls to the Main Thread will resolve the SIGILL error.
To Reproduce
Steps to Reproduce (STR)
Environment Setup:
Ensure you are using macOS 10.15 or higher.
Install Python 3.13.x.
Verify that System Integrity Protection is enabled (as per your log).
Create the Trigger Script: Save the following code as repro_bug.py. This script uses ctypes to call the exact function found in your crash log (TSMGetInputSourceProperty) from a background thread.
Python
import ctypes
import threading
import time
Load the framework mentioned in the crash log
hitoolbox = ctypes.cdll.LoadLibrary('/System/Library/Frameworks/Carbon.framework/Frameworks/HIToolbox.framework/HIToolbox')
def trigger_crash():
print("Thread 8: Attempting illegal system call...")
# This function requires the Main Thread queue on macOS
# Calling it here will trigger the libdispatch assertion failure
hitoolbox.TSMGetInputSourceProperty(None, None)
print("Main Thread: Starting background worker...")
thread = threading.Thread(target=trigger_crash)
thread.start()
thread.join()
Execute the Script: Open the Terminal and run:
Bash
python3 repro_bug.py
Observe the Result: The application will not exit with a Python error. Instead, it will disappear instantly, and the Terminal will display: Illegal instruction: 4
Verify the Crash Log: Open the Console.app on macOS or check /Library/Logs/DiagnosticReports/. The new log will match your original report:
Crashed Thread: 8 (or whichever worker thread was used).
Assertion: Block was expected to execute on queue [com.apple.main-thread].
Visualizing the Fault Path
The crash occurs because the execution flow crosses a "red line" established by the macOS kernel for system security and stability.
Summary for the Bug Report
Reproduction Logic: The issue is reproducible by invoking any HIToolbox or CoreFoundation property getter that interacts with the window server or input methods from a non-main dispatch queue. Python 3.13’s threading implementation exposes this immediately as it lacks the global locks that occasionally "masked" these race conditions in older versions.
Expected behavior
Feature | Actual Behavior (The Bug) | Expected Behavior (The Fix) -- | -- | -- Stability | Crashes with SIGILL immediately. | Runs indefinitely without interruption. Threading | Background thread calls System APIs. | Background thread communicates via Queue. OS Interface | Violates libdispatch assertions. | Complies with macOS Main Thread constraints. User Experience | Application disappears (Fatal). | Application remains responsive and fluid. Python Version | 3.13 triggers strict memory/thread checks. | Code is refactored to be 3.13-compliant.URL to the issue
No response
Screenshots
""Browsers
Other
Operating System
macOS
Browser Version
No response
Relevant log output
Log Type: Threading Assertion Failure (SIGILL)
Component: libdispatch.dylib / HIToolbox
Assertion: Block was expected to execute on queue [com.apple.main-thread]
--------------------------------------------------------------------------------
CRASHED THREAD: Thread 8
--------------------------------------------------------------------------------
0 libdispatch.dylib 0x00007fff7262c8f1 _dispatch_assert_queue_fail + 99
1 libdispatch.dylib 0x00007fff7262c886 dispatch_assert_queue + 122
2 com.apple.HIToolbox 0x00007fff376ffdc2 islGetInputSourceListWithAdditions + 119
3 com.apple.HIToolbox 0x00007fff377025b8 isValidateInputSourceRef + 90
4 com.apple.HIToolbox 0x00007fff37702480 TSMGetInputSourceProperty + 30 <--- [FATAL CALL]
5 libffi.dylib 0x00007fff7042f905 ffi_call_unix64 + 85
6 libffi.dylib 0x00007fff7042f244 ffi_call_int + 694
7 _ctypes.cpython-313 0x0000000107cc0eda _ctypes_callproc + 1114
8 _ctypes.cpython-313 0x0000000107cb7218 PyCFuncPtr_call + 312
9 org.python.python 0x00000001042a6e55 _PyEval_EvalFrameDefault + 51397
10 org.python.python 0x00000001041046db gen_iternext + 139
11 org.python.python 0x0000000104294ce7 builtin_next + 71
...
17 org.python.python 0x0000000104404782 thread_run + 146
18 org.python.python 0x0000000104374584 pythread_wrapper + 36
--------------------------------------------------------------------------------
REASONING FOR LOG SELECTION:
--------------------------------------------------------------------------------
1. Frame 4 shows the target: TSMGetInputSourceProperty. This is a "Main Thread Only" API.
2. Frame 0-1 shows the watchdog: libdispatch detected the call was on Thread 8.
3. Frame 17-18 confirms this was a standard Python `threading.Thread` object.Additional context
FIX IT