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

Python 3.10.0 crashes on MacOS x86_64 #522

Closed
1 task done
akrherz opened this issue Nov 11, 2021 · 33 comments · Fixed by #525
Closed
1 task done

Python 3.10.0 crashes on MacOS x86_64 #522

akrherz opened this issue Nov 11, 2021 · 33 comments · Fixed by #525

Comments

@akrherz
Copy link

akrherz commented Nov 11, 2021

Issue: Two conda-forge repos having strange crashes within CI on MacOS with python 3.10.0

Note: I am not a mac user, but am just attempting to help conda-forge repos get green CI builds :)

Examples of CI crashes: conda-forge/magics-feedstock#106 and conda-forge/shapely-feedstock#92

I do have an old mac that I am able to reproduce the shapely crashes and have gotten some iterative feedback here along with lldb output: shapely/shapely#1227

Does anybody here have interest / mac experience to help figure out what is wrong? Thanks!

@dopplershift
Copy link
Member

dopplershift commented Nov 16, 2021

I'll add to this (because I think they are related) the Abort trap: 6 (the same as the error from Magics) that we're seeing in conda-forge/rtree-feedstock#41 and conda-forge/python-libarchive-c-feedstock#29. I'll note that the last two appear to have the aborts coming out of libffi, which is also where Shapely is crashing.

@dopplershift
Copy link
Member

dopplershift commented Nov 16, 2021

So something is definitely broken about ctypes in the conda-forge build. Shapely builds and runs tests fine on my system with Homebrew Python 3.10; more importantly, if I copy _ctypes.cpython-310-darwin.so from the Homebrew Python 3.10 into my conda-forge one, Shapely's tests run without crashing. It should be noted that a difference between the two is that Homebrew's _ctypes is linked to /usr/lib/libffi.dylib.

@dopplershift
Copy link
Member

I took the Python recipe and did a local build where I removed libffi from host. Running conda build for all four of rtree, python-libarchive-c, shapely, and magics worked fine (tests completed) using my local build of Python.

Is there any particular reason to avoid the macOS copy of libffi? This Python issue would seem to indicate that using the system copy for macos is the norm.

@xhochy
Copy link
Member

xhochy commented Nov 16, 2021

Pinging @isuruf and @erykoff here as they have had to experience a lot of issues with libffi on macOS.

One important difference to note here is that these issues only seem to happen on osx-64 where we historically have build with conda-forge's libffi already for the last releases. Only osx-arm64 now also uses the c-f libffi, too.

@jakirkham
Copy link
Member

jakirkham commented Nov 16, 2021

Actually this raises a question that is unclear (at least to me). Is this occurring with macOS ARM or x86?

Edit: If it is ARM related, this comment ( libffi/libffi#571 (comment) ) and related issue may be of interest

@erykoff
Copy link
Contributor

erykoff commented Nov 16, 2021

I will investigate. What is notable is that the issue above to get python to work with both system and forge libffi was first put in 3.10 and then backported. But 3.9 isn’t exhibiting this problem.

@erykoff
Copy link
Contributor

erykoff commented Nov 16, 2021

Interesting, I was unable to replicate the segfault with the shapely py3.10 build on osx-arm64. So it may be limited to x86 (or possibly macos<11). I will try to replicate locally on x86/macos 10.14.

@dopplershift
Copy link
Member

For completeness, my tests locally were done on macOS 11.6.1.

@akrherz
Copy link
Author

akrherz commented Nov 16, 2021

My reproducer is on macOS 10.13.6 🐄 and I have not seen this issue reproduced on arm64

@jakirkham jakirkham changed the title Python 3.10.0 crashes on MacOS Python 3.10.0 crashes on MacOS x86_64 Nov 16, 2021
@jakirkham
Copy link
Member

Retitled the issue to indicate this is an x86_64 issue

@erykoff
Copy link
Contributor

erykoff commented Nov 18, 2021

I have been digging, and haven't figured out what's going wrong. Within shapely itself it crashes when the c++ throws an error, but only then (that is, successful ctypes calls work just fine). (I don't know if that's a clue or a coincidence). However, I have also been able to replicate the crash running on my M1 macbook when trying it in x86 rosetta translation. So that does make debugging marginally easier.

@jakirkham
Copy link
Member

Do you have the gdb or lldb backtrace? Maybe worth sharing here

@akrherz
Copy link
Author

akrherz commented Nov 18, 2021

Do you have the gdb or lldb backtrace? Maybe worth sharing here

I added one to shapely/shapely#1227, copying here:

$ lldb python
(lldb) target create "python"
Current executable set to 'python' (x86_64).
(lldb) run -m pytest tests/test_invalid_geometries.py
Process 32591 launched: '/Users/akrherz/miniconda3/envs/py310/bin/python' (x86_64)
============================= test session starts ==============================
platform darwin -- Python 3.10.0, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
numpy: 1.21.4
rootdir: /Users/akrherz/Shapely-1.8.0, configfile: setup.cfg
collected 1 item                                                               

tests/test_invalid_geometries.py Process 32591 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
    frame #0: 0x00000001017fefc3
Target 0: (python) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
  * frame #0: 0x00000001017fefc3
    frame #1: 0x0000000105cde250 libgeos_c.dylib`GEOSIntersection_r + 176
    frame #2: 0x0000000105cd1d92 libffi.8.dylib`ffi_call_unix64 + 82
    frame #3: 0x0000000105cd1429 libffi.8.dylib`ffi_call_int + 761
    frame #4: 0x0000000105cb3456 _ctypes.cpython-310-darwin.so`_ctypes_callproc + 790
    frame #5: 0x0000000105cad652 _ctypes.cpython-310-darwin.so`PyCFuncPtr_call + 274
    frame #6: 0x0000000100089d1c python`_PyObject_Call + 108
    frame #7: 0x000000010029eeea python`partial_call + 106
    frame #8: 0x0000000100089d1c python`_PyObject_Call + 108
    frame #9: 0x00000001001bfe93 python`_PyEval_EvalFrameDefault + 19843
    frame #10: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #11: 0x0000000100088cee python`_PyObject_FastCallDictTstate + 110
    frame #12: 0x000000010011c0f4 python`slot_tp_call + 196
    frame #13: 0x0000000100088a66 python`_PyObject_MakeTpCall + 134
    frame #14: 0x00000001001c9956 python`call_function + 438
    frame #15: 0x00000001001bfcd9 python`_PyEval_EvalFrameDefault + 19401
    frame #16: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #17: 0x000000010008d21b python`method_vectorcall + 363
    frame #18: 0x00000001001bfe93 python`_PyEval_EvalFrameDefault + 19843
    frame #19: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #20: 0x00000001001c9850 python`call_function + 176
    frame #21: 0x00000001001bfc43 python`_PyEval_EvalFrameDefault + 19251
    frame #22: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #23: 0x00000001001c9850 python`call_function + 176
    frame #24: 0x00000001001bfc43 python`_PyEval_EvalFrameDefault + 19251
    frame #25: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #26: 0x000000010008d14e python`method_vectorcall + 158
    frame #27: 0x00000001001c9850 python`call_function + 176
    frame #28: 0x00000001001bfcd9 python`_PyEval_EvalFrameDefault + 19401
    frame #29: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #30: 0x00000001001c9850 python`call_function + 176
    frame #31: 0x00000001001bfc43 python`_PyEval_EvalFrameDefault + 19251
    frame #32: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #33: 0x000000010008d14e python`method_vectorcall + 158
    frame #34: 0x0000000100089aec python`PyVectorcall_Call + 204
    frame #35: 0x00000001001bfe93 python`_PyEval_EvalFrameDefault + 19843
    frame #36: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #37: 0x0000000100088d77 python`_PyObject_FastCallDictTstate + 247
    frame #38: 0x000000010011c0f4 python`slot_tp_call + 196
    frame #39: 0x0000000100088a66 python`_PyObject_MakeTpCall + 134
    frame #40: 0x00000001001c9956 python`call_function + 438
    frame #41: 0x00000001001bfd78 python`_PyEval_EvalFrameDefault + 19560
    frame #42: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #43: 0x00000001001c9850 python`call_function + 176
    frame #44: 0x00000001001bfc43 python`_PyEval_EvalFrameDefault + 19251
    frame #45: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #46: 0x00000001001bfe93 python`_PyEval_EvalFrameDefault + 19843
    frame #47: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #48: 0x00000001001c9850 python`call_function + 176
    frame #49: 0x00000001001c1230 python`_PyEval_EvalFrameDefault + 24864
    frame #50: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #51: 0x000000010008d14e python`method_vectorcall + 158
    frame #52: 0x00000001001c9850 python`call_function + 176
    frame #53: 0x00000001001c1230 python`_PyEval_EvalFrameDefault + 24864
    frame #54: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #55: 0x0000000100088d77 python`_PyObject_FastCallDictTstate + 247
    frame #56: 0x000000010011c0f4 python`slot_tp_call + 196
    frame #57: 0x0000000100089d1c python`_PyObject_Call + 108
    frame #58: 0x00000001001bfe93 python`_PyEval_EvalFrameDefault + 19843
    frame #59: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #60: 0x00000001001c9850 python`call_function + 176
    frame #61: 0x00000001001bfcd9 python`_PyEval_EvalFrameDefault + 19401
    frame #62: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #63: 0x000000010008d14e python`method_vectorcall + 158
    frame #64: 0x00000001001c9850 python`call_function + 176
    frame #65: 0x00000001001bfd78 python`_PyEval_EvalFrameDefault + 19560
    frame #66: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #67: 0x00000001001bfe93 python`_PyEval_EvalFrameDefault + 19843
    frame #68: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #69: 0x00000001001c9850 python`call_function + 176
    frame #70: 0x00000001001bfcd9 python`_PyEval_EvalFrameDefault + 19401
    frame #71: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #72: 0x00000001001c9850 python`call_function + 176
    frame #73: 0x00000001001bfd78 python`_PyEval_EvalFrameDefault + 19560
    frame #74: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #75: 0x00000001001bfe93 python`_PyEval_EvalFrameDefault + 19843
    frame #76: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #77: 0x00000001001c9850 python`call_function + 176
    frame #78: 0x00000001001c1230 python`_PyEval_EvalFrameDefault + 24864
    frame #79: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #80: 0x000000010008d14e python`method_vectorcall + 158
    frame #81: 0x00000001001c9850 python`call_function + 176
    frame #82: 0x00000001001c1230 python`_PyEval_EvalFrameDefault + 24864
    frame #83: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #84: 0x0000000100088d77 python`_PyObject_FastCallDictTstate + 247
    frame #85: 0x000000010011c0f4 python`slot_tp_call + 196
    frame #86: 0x0000000100088a66 python`_PyObject_MakeTpCall + 134
    frame #87: 0x00000001001c9956 python`call_function + 438
    frame #88: 0x00000001001bfd78 python`_PyEval_EvalFrameDefault + 19560
    frame #89: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #90: 0x00000001001bfe93 python`_PyEval_EvalFrameDefault + 19843
    frame #91: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #92: 0x00000001001c9850 python`call_function + 176
    frame #93: 0x00000001001c1230 python`_PyEval_EvalFrameDefault + 24864
    frame #94: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #95: 0x000000010008d14e python`method_vectorcall + 158
    frame #96: 0x00000001001c9850 python`call_function + 176
    frame #97: 0x00000001001c1230 python`_PyEval_EvalFrameDefault + 24864
    frame #98: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #99: 0x0000000100088d77 python`_PyObject_FastCallDictTstate + 247
    frame #100: 0x000000010011c0f4 python`slot_tp_call + 196
    frame #101: 0x0000000100088a66 python`_PyObject_MakeTpCall + 134
    frame #102: 0x00000001001c9956 python`call_function + 438
    frame #103: 0x00000001001bfd78 python`_PyEval_EvalFrameDefault + 19560
    frame #104: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #105: 0x00000001001c9850 python`call_function + 176
    frame #106: 0x00000001001bfcd9 python`_PyEval_EvalFrameDefault + 19401
    frame #107: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #108: 0x00000001001c9850 python`call_function + 176
    frame #109: 0x00000001001bfcd9 python`_PyEval_EvalFrameDefault + 19401
    frame #110: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #111: 0x00000001001bfe93 python`_PyEval_EvalFrameDefault + 19843
    frame #112: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #113: 0x00000001001c9850 python`call_function + 176
    frame #114: 0x00000001001c1230 python`_PyEval_EvalFrameDefault + 24864
    frame #115: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #116: 0x000000010008d14e python`method_vectorcall + 158
    frame #117: 0x00000001001c9850 python`call_function + 176
    frame #118: 0x00000001001c1230 python`_PyEval_EvalFrameDefault + 24864
    frame #119: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #120: 0x0000000100088d77 python`_PyObject_FastCallDictTstate + 247
    frame #121: 0x000000010011c0f4 python`slot_tp_call + 196
    frame #122: 0x0000000100088a66 python`_PyObject_MakeTpCall + 134
    frame #123: 0x00000001001c9956 python`call_function + 438
    frame #124: 0x00000001001bfd78 python`_PyEval_EvalFrameDefault + 19560
    frame #125: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #126: 0x00000001001c9850 python`call_function + 176
    frame #127: 0x00000001001bfcd9 python`_PyEval_EvalFrameDefault + 19401
    frame #128: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #129: 0x00000001001c9850 python`call_function + 176
    frame #130: 0x00000001001c1230 python`_PyEval_EvalFrameDefault + 24864
    frame #131: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #132: 0x00000001001b3ac2 python`builtin_exec + 354
    frame #133: 0x00000001000ef7f5 python`cfunction_vectorcall_FASTCALL + 85
    frame #134: 0x00000001001c9850 python`call_function + 176
    frame #135: 0x00000001001bfcd9 python`_PyEval_EvalFrameDefault + 19401
    frame #136: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #137: 0x00000001001c9850 python`call_function + 176
    frame #138: 0x00000001001bfcd9 python`_PyEval_EvalFrameDefault + 19401
    frame #139: 0x00000001001b9833 python`_PyEval_Vector + 387
    frame #140: 0x000000010025dc82 python`pymain_run_module + 258
    frame #141: 0x000000010025d717 python`pymain_run_python + 599
    frame #142: 0x000000010025d465 python`Py_RunMain + 37
    frame #143: 0x000000010025ea61 python`pymain_main + 49
    frame #144: 0x0000000100001718 python`main + 56
    frame #145: 0x00007fff6acc7015 libdyld.dylib`start + 1
    frame #146: 0x00007fff6acc7015 libdyld.dylib`start + 1
(lldb) 

@ihnorton
Copy link

Is this known to reproduce on macOS 10.14 / x86_64? I tried to reproduce the related libarchive issue locally on 10.14, but did not.

@jakirkham
Copy link
Member

Thanks @akrherz! 😄

Would you be able to share some more details from the environment where this occurs as well? Would suggest running the command conda list --explicit --md5 and including that info here. That should be enough info for anyone to create the exact same environment

@erykoff
Copy link
Contributor

erykoff commented Nov 19, 2021

Here is a script I put together that will segmentation fault (and show a backtrace with lldb). I get the same results on an old x86 laptop running 10.14, and an M1 running 11.6 using x86 mambaforge with rosetta. The native arm64 seems to work fine.

mamba create -n shapelycrash python=3.10 c-compiler pip cython numpy geos
conda activate shapelycrash
curl -OL https://pypi.io/packages/source/S/Shapely/Shapely-1.8.0.tar.gz
tar -xzvf Shapely-1.8.0.tar.gz
cd Shapely-1.8.0
rm -rf shapely/speedups/_speedups.c
rm -rf shapely/vectorized/_vectorized.c
python -m cython shapely/speedups/_speedups.pyx
python -m cython shapely/vectorized/_vectorized.pyx
export GEOS_DIR=${CONDA_PREFIX}
python -m pip install --no-deps --ignore-installed .
echo "from shapely.wkt import loads; loads('JUNK')" > crash.py
python crash.py
# segmentation fault: 11
lldb python -- crash.py
(lldb) run
(lldb) bt

The backtrace in this case looks like:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xab)
  * frame #0: 0x0000000109420a0b _ctypes.cpython-310-darwin.so`closure_fcn + 11
    frame #1: 0x000000010946e78f libffi.8.dylib`ffi_closure_unix64_inner + 591
    frame #2: 0x000000010946ef0c libffi.8.dylib`ffi_closure_unix64 + 72
    frame #3: 0x000000010aa37b36 libgeos_c.1.16.0.dylib`GEOSContextHandle_HS::ERROR_MESSAGE(char const*, ...) + 214
    frame #4: 0x000000010aa3bd75 libgeos_c.1.16.0.dylib`GEOSWKTReader_read_r + 293
    frame #5: 0x000000010946ed72 libffi.8.dylib`ffi_call_unix64 + 82
    frame #6: 0x000000010946e429 libffi.8.dylib`ffi_call_int + 761
    frame #7: 0x0000000109422456 _ctypes.cpython-310-darwin.so`_ctypes_callproc + 790
    frame #8: 0x000000010941c652 _ctypes.cpython-310-darwin.so`PyCFuncPtr_call + 274
    frame #9: 0x0000000100089bac python`_PyObject_Call + 108

@jakirkham
Copy link
Member

Nicely done! 👏

So should loads('JUNK') error normally? IOW we should see an exception, but that doesn't work correctly causing a crash instead?

@jorisvandenbossche
Copy link
Member

So should loads('JUNK') error normally? IOW we should see an exception, but that doesn't work correctly causing a crash instead?

Indeed, that should normally error. On linux (Python 3.10, latest conda-forge shapely 1.8) this gives me:

>>> import shapely.wkt
>>> shapely.wkt.loads('JUNK')
ParseException: Unknown type: 'JUNK'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/joris/miniconda3/envs/test-shapely/lib/python3.10/site-packages/shapely/wkt.py", line 22, in loads
    return geos.WKTReader(geos.lgeos).read(data)
  File "/home/joris/miniconda3/envs/test-shapely/lib/python3.10/site-packages/shapely/geos.py", line 299, in read
    raise WKTReadingError(
shapely.errors.WKTReadingError: Could not create geometry because of errors while reading input.

This is coming from an exception in C++, which the C API layer of GEOS turns into a error return value (a null pointer in this case), which then Shapely should normally catch and raise a Python error. The code specifically for this failing example is https://github.com/Toblerity/Shapely/blob/d1cda1f97227f864710cd49d3f3577fa506ff65f/shapely/geos.py#L291-L299

@jorisvandenbossche
Copy link
Member

Another crash came from the test_invalid_intersection test, so I suppose the following:

>>> from shapely.geometry import Polygon
>>> polygon_invalid = Polygon(((0, 0), (1, 1), (1, -1), (0, 1), (0, 0)))
>>> polygon = Polygon(((-.5, -.5), (-.5, .5), (.5, .5), (.5, -5)))
>>> polygon_invalid.intersection(polygon)
TopologyException: Input geom 0 is invalid: Self-intersection at 0.33333333333333337 0.33333333333333337
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/joris/miniconda3/envs/test-shapely/lib/python3.10/site-packages/shapely/geometry/base.py", line 689, in intersection
    return geom_factory(self.impl['intersection'](self, other))
  File "/home/joris/miniconda3/envs/test-shapely/lib/python3.10/site-packages/shapely/topology.py", line 72, in __call__
    self._check_topology(err, this, other)
  File "/home/joris/miniconda3/envs/test-shapely/lib/python3.10/site-packages/shapely/topology.py", line 37, in _check_topology
    raise TopologicalError(
shapely.errors.TopologicalError: The operation 'GEOSIntersection_r' could not be performed. Likely cause is invalidity of the geometry <shapely.geometry.polygon.Polygon object at 0x7f5df9622740>

Also here it is a case of catching an error return / translating an error handle message into a python log.
The lldb backtrace from @erykoff also includes GEOSContextHandle_HS::ERROR_MESSAGE(char const*, ...) which might indicate it has something to do with this error message handling.

In case it is relevant, the C++ code that calls this ERROR_MESSAGE in this case is at https://github.com/libgeos/geos/blob/2d1c9d7a1857048553d7f0719511df1290da1609/capi/geos_ts_c.cpp#L407-L413. And the Python ctypes code that handles this error message is at https://github.com/Toblerity/Shapely/blob/d1cda1f97227f864710cd49d3f3577fa506ff65f/shapely/geos.py#L250-L271

@jakirkham
Copy link
Member

Interesting yeah was about to ask about this. As it seems like the problem would happen on line 297 in the original example. All the code that comes afterwards is pure Python. So this wouldn't explain the C-level error handling whereas line 297 would. Are we able to reproduce just with a call to GEOSWKTReader_read?

@jakirkham
Copy link
Member

Am now wondering if it has something to do with the variadic arguments.

@jorisvandenbossche
Copy link
Member

I can't test myself (on linux the snippet works fine), but a potential reproducer just with GEOSWKTReader_read would be:

>>> from ctypes import c_char_p
>>> c_string = c_char_p("JUNK".encode())
>>> from shapely.geos import lgeos
>>> reader = lgeos.GEOSWKTReader_create()
>>> res = lgeos.GEOSWKTReader_read(reader, c_string)
ParseException: Unknown type: 'JUNK'
>>> res is None
True

@isuruf
Copy link
Member

isuruf commented Nov 19, 2021

Does libffi=3.3 fix the issue? conda-forge/llvmlite-feedstock#58 seems to suggest so

@mbargull
Copy link
Member

Does libffi=3.3 fix the issue? conda-forge/llvmlite-feedstock#58 seems to suggest so

Yes, I've just rebuilt locally with 3.3 and tested it out. All things pass now for the tests from conda-forge/llvmlite-feedstock#58 .

@jakirkham
Copy link
Member

This Python bug demonstrates crashes with Python’s test suite on macOS x86_64 using libffi 3.4.2, which don’t occur with libffi 3.3

https://bugs.python.org/issue44556

@dopplershift
Copy link
Member

@jorisvandenbossche 's example was crashing for me. Rebuilding Python with libffi allowed me to build a shapely package (instead of crashing), and the snippet no longer crashes for me either.

@erykoff
Copy link
Contributor

erykoff commented Nov 19, 2021

Great find on the python bug! So this isn’t limited to the conda forge builds.

@h-vetinari
Copy link
Member

I think this is probably the same failure that I've encountered on the clangdev feedstock just after 3.10 came out (and then got selected in the noarch-build of python-clang: conda-forge/clangdev-feedstock#158

Things worked when restricting to <3.10, but failed otherwise. The recent discussion around llvmlite reminded me of this, and I tried to see if this occurs also on LLVM 12 (so, independently of the newest LLVM version), and indeed, this is the case: conda-forge/clangdev-feedstock#159

@erykoff
Copy link
Contributor

erykoff commented Nov 19, 2021

Okay, I'm knee deep in autoconf pain, but what seems to be happening is that something in configure was updated and it no longer is finding LIBFFI_INCLUDEDIR. So python 3.10 defaults to the SDK version (which happens to be 3.3) while 3.9.7 uses the conda forge version. There were some struct changes in between libffi 3.3 and 3.4.2 so when ctypes is compiled against the wrong header when you actually run (linking conda forge libffi) then BOOM.

Hopefully I'll have more soon.

@erykoff
Copy link
Contributor

erykoff commented Nov 19, 2021

I have found the problem! For whatever reason (and I am not sufficiently knowledgeable in autoconf to debug a 20000 line configure script), the default sussing of pkg-config in python 3.9 configure and earlier yields the fully qualified path name, but in 3.10 it just yields x86_64-apple-darwin13.4.0-pkg-config (no path). And for whatever reason without the full path this fails:
https://github.com/python/cpython/blob/v3.10.0/configure#L10582-L10586
And when it doesn't have the correct LIBFFI_INCLUDE_DIR then it uses the SDK, we get the version conflict, and buffer overruns galore.

The conda forge solution is to add export PKG_CONFIG=/full/path/to/pkgconfig. And I have an important meeting in a few minutes and can't take care of the relevant bash-fu.

@jakirkham
Copy link
Member

jakirkham commented Nov 19, 2021

Thanks for the sleuthing @erykoff! 😄

This is an interesting discovery. We do set PKG_CONFIG in a few recipes. Here's one example we can draw from.

A few lines above that it is suggested we do this in compiler activation. May be worth following up on as it seems not specifying this path is causing us pain in a few places (this being one of them). It's worth noting there is some trickiness here

@jakirkham
Copy link
Member

I've tried to write this up in the Python bug ( https://bugs.python.org/issue44556 ). Feel free to add any additional details and/or correct me as needed

@iainrussell
Copy link

Thanks everyone!

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

Successfully merging a pull request may close this issue.