An Objective-C exception (NSException) terminates the Python process
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 30/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- c, macos, objective-c, python
- Domain
- desktop-dev, testing
Research direction
Start at ObjcMethod.__call__ in pyobjus/pyobjus.pyx around the direct ffi_call, then trace how the extension is built so an Objective-C source can be compiled with -fobjc-exceptions. The fix is a small Objective-C wrapper around ffi_call that catches NSException, passes its name and reason back, and lets __call__ raise an ObjcException; verify unwinding on arm64 and x86_64. Done means the out-of-range objectAtIndex_ example raises a catchable Python exception, covered by a subprocess test so pre-fix aborts do not kill the runner.
Written by the indexing model from the issue text.
Description
Summary
An Objective-C exception thrown by a method called through pyobjus terminates the whole process. It can't be caught in Python:
from pyobjus import autoclass
NSArray = autoclass("NSArray")
a = NSArray.arrayWithObject_(NSArray.array())
try:
a.objectAtIndex_(5)
except Exception as e:
print("caught:", e)
print("not reached")
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSSingleObjectArrayI objectAtIndex:]: index 5 beyond bounds [0 .. 0]'
*** First throw call stack:
(
0 CoreFoundation ... __exceptionPreprocess + 176
1 libobjc.A.dylib ... objc_exception_throw + 88
2 CoreFoundation ... -[__NSSingleObjectArrayI objectAtIndex:] + 328
3 libffi.dylib ... ffi_call_SYSV + 80
4 libffi.dylib ... ffi_call_int + 1220
5 pyobjus.cpython-314-darwin.so ... __pyx_pf_7pyobjus_10ObjcMethod_10__call__ + 23812
...
)
libc++abi: terminating due to uncaught exception of type NSException
Exit status 134 (SIGABRT); nothing after the call runs, including the except.
(macOS 26, arm64, master at 9fb0619.)
Impact
Foundation reports programmer errors this way: out-of-range indexes (NSRangeException), nil passed where an object is required, mutating an immutable collection, and invalid arguments (NSInvalidArgumentException), and so on. In an app, a mistake in one call takes down the whole app with no Python traceback, and in a test run it kills pytest.
Cause
ObjcMethod.__call__ calls ffi_call directly from Cython, and pyobjus compiles no Objective-C, so nothing between the method and Python can catch the exception:
Possible direction
Make the ffi_call from a small Objective-C function (compiled with -fobjc-exceptions) that wraps it in @try / @catch, and hands the exception back so __call__ can raise an ObjcException carrying the exception's name and reason. The exception has to unwind through libffi's ffi_call frame to reach the @catch, so that needs checking on both arm64 and x86_64. PyObjC turns these exceptions into Python exceptions in a similar way.
A test is easy: call objectAtIndex_ out of range and assert that an exception is raised. It needs to run in a subprocess, since before the fix it aborts the interpreter.
- Dominant language
- Python
- Stars
- 192
- Forks
- 48
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 22
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from kivy/pyobjus
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 80/100
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 45/100
Maintainers usually reply within 1 day
-
Difficulty 3/5 1-2 days Newbie friendliness 50/100
Maintainers usually reply within 1 day
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
vllm-project/vllm#64845 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
dekobon/big-code-analysis#1729 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
pydantic/pydantic-ai#12091 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100