You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
On macos arm64, objc.objc_msgSend seg-faults when called from ipython #562
Related to #561 , ipython/ipykernel/etc will seg-fault when running the following test code (based on appnope):
import ctypes
import ctypes.util
objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('objc'))
def _utf8(s):
"""ensure utf8 bytes"""
if not isinstance(s, bytes):
s = s.encode('utf8')
return s
def n(name):
"""create a selector name (for methods)"""
return objc.sel_registerName(_utf8(name))
def C(classname):
"""get an ObjC Class by name"""
return objc.objc_getClass(_utf8(classname))
NSString = C('NSString')
objc.objc_msgSend(NSString, n("stringWithUTF8String:"), _utf8("reason"))
The stack trace on an arm64 mac (DTK) says: python[97504:4905234] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSString stringWithUTF8String:]: NULL cString'
Note that this code will work with both system python (macos 11.0.1) and conda-forge python 3.9.0 for osx-arm64. However, it will seg-fault with ipython/ipykernel from conda-forge or with ipython installed with the system python via pip.
at the top breaks it too. Nothing ipython it seems. Actually breaks it is the wrong word. Without the import, NSString == 0. With it, it has a value and crashes.
@geohot I think the key part of your fix is definitely setting the argtypes for each individual call, which was missing before and probably incorrect. (Though why this worked with python and not ipython is a mystery).
It's unclear to me if the None issue is actually an issue, the code runs without error (though maybe the nope is a no-op in that case, I'm not sure how to check).
Finally, I traced down the mystery of the from urllib.request import python to the import _scproxy call in urllib.
And it seems that the key here is that we need to load the Foundation library which _scproxy pulls in (along with a ton of other stuff): _ = ctypes.cdll.LoadLibrary(ctypes.util.find_library('Foundation'))
The None thing is definitely an issue, it just means it couldn't find the class, and won't be able to call methods on it. The reason python and ipython were different is just because ipython imported urllib before your code, which loaded Foundation.
You found the fix in the other thread though, obviously you can't find NSString if you don't load Foundation! Fixed in my appnope PR.
I believe this also requires CPython 3.9.1 by python/cpython#21249. ctypes dyld in general doesn't work with cpython 3.9.0 on macOS 11. The patches have been backported in the latest homebrew Python 3.9.0 and conda-forge Python 3.9 builds (3.8, too, perhaps?).
Activity
geohot commentedon Nov 28, 2020
Nice repro! Breaks from normal python3 (3.9 from homebrew) by adding
to the top. Trying to figure out exactly what it is that breaks it. Relevant traceback
geohot commentedon Nov 28, 2020
Tracked it back through ipython.
at the top breaks it too. Nothing ipython it seems. Actually breaks it is the wrong word. Without the import, NSString == 0. With it, it has a value and crashes.
Adding
fixes it, in both python and ipython.
erykoff commentedon Nov 28, 2020
@geohot I think the key part of your fix is definitely setting the
argtypesfor each individual call, which was missing before and probably incorrect. (Though why this worked with python and not ipython is a mystery).It's unclear to me if the
Noneissue is actually an issue, the code runs without error (though maybe the nope is a no-op in that case, I'm not sure how to check).Finally, I traced down the mystery of the
from urllib.request import pythonto theimport _scproxycall inurllib.And it seems that the key here is that we need to load the
Foundationlibrary which_scproxypulls in (along with a ton of other stuff):_ = ctypes.cdll.LoadLibrary(ctypes.util.find_library('Foundation'))geohot commentedon Nov 28, 2020
The None thing is definitely an issue, it just means it couldn't find the class, and won't be able to call methods on it. The reason python and ipython were different is just because ipython imported urllib before your code, which loaded Foundation.
You found the fix in the other thread though, obviously you can't find NSString if you don't load Foundation! Fixed in my appnope PR.
minrk commentedon Dec 2, 2020
I believe this also requires CPython 3.9.1 by python/cpython#21249. ctypes dyld in general doesn't work with cpython 3.9.0 on macOS 11. The patches have been backported in the latest homebrew Python 3.9.0 and conda-forge Python 3.9 builds (3.8, too, perhaps?).