jim-easterbrook / python-gphoto2

Python interface to libgphoto2
GNU Lesser General Public License v3.0
374 stars 59 forks source link

Segmentation Fault segfault on gp.Camera.autodetect() on Github Actions Runner #158

Closed mgineer85 closed 1 year ago

mgineer85 commented 1 year ago

This page is for reporting problems with the Python interface to libgphoto2. If your question is about using libgphoto2 you should ask on the gphoto2 mailing list.

Your system What version of Python are you using? Ubuntu 22.04

What version of libgphoto2 have you installed? ?

How have you installed (or attempted to install) python-gphoto2? via pip

Your problem Since two weeks something has changed maybe in github actions runner which makes the command gp.Camera.autodetect() fail with segmentation fault: https://github.com/mgrl/photobooth-app/actions/runs/5563284262/jobs/10162147889#step:6:333

Is this up to python-gphoto2 or did something change to libgphoto2? Otherwise it might be the environment?

mgineer85 commented 1 year ago

Found there is a new version released. I will check whether this is a difference.

mgineer85 commented 1 year ago

Following version on github actions hosted runner fails if gp.Camera.autodetect() is issued: 2023-07-16 07:00:16 [ INFO] python-gphoto2: 2.3.5 (gphoto2.py:72) 2023-07-16 07:00:16 [ INFO] libgphoto2: ['2.5.30', 'standard camlib set (ax203 canon digigr8 dimagev directory docupen jl2005a jl2005c kodak_dc240 lumix mars pentax ptp2 ricoh_g3 sierra sonix sq905 st2205 topfield tp6801)', 'gcc (C compiler used)', 'no ltdl (for portable loading of camlibs)', 'EXIF (for special handling of EXIF files)'] (gphoto2.py:73) 2023-07-16 07:00:16 [ INFO] libgphoto2_port: ['0.12.1', 'iolibs: disk ptpip serial usb usbdiskdirect usbscsi', 'gcc (C compiler used)', 'no ltdl (for portable loading of iolibs)', 'EXIF (for vusb)', 'USB (libusb0, for USB cameras)', 'serial (for serial cameras)', 'no resmgr (serial port access and locking)', 'no ttylock (serial port locking)', 'no lockdev (serial port locking)'] (gphoto2.py:74)

Following version on github actions selfhosted-runner succeed if gp.Camera.autodetect() is issued: 2023-07-15 19:15:52 [ INFO] python-gphoto2: 2.3.4 (gphoto2.py:72) 2023-07-15 19:15:52 [ INFO] libgphoto2: ['2.5.30.1', 'standard camlib set SKIPPING SOME (ax203 canon digigr8 dimagev directory jl2005a jl2005c kodak_dc240 mars pentax ptp2 ricoh_g3 sierra sonix sq905 st2205 topfield tp6801 SKIPPING docupen lumix)', 'gcc (C compiler used)', 'no ltdl (for portable loading of camlibs)', 'EXIF (for special handling of EXIF files)'] (gphoto2.py:73) 2023-07-15 19:15:52 [ INFO] libgphoto2_port: ['0.12.2', 'iolibs: disk ptpip serial vusb', 'gcc (C compiler used)', 'no ltdl (for portable loading of iolibs)', 'EXIF (for vusb)', 'no USB (for USB cameras)', 'serial (for serial cameras)', 'no resmgr (serial port access and locking)', 'no ttylock (serial port locking)', 'no lockdev (serial port locking)'] (gphoto2.py:74)

mgineer85 commented 1 year ago

reverting to 2.3.4 on hosted runner works.

Any idea what went wrong in latest version?

jim-easterbrook commented 1 year ago

Sorry for not responding to this sooner, I was out yesterday. If I understand correctly you're using pip to install python-gphoto2 on a GitHub runner. The list of camlibs doesn't match those in the python-gphoto2 binary wheels so I assume your runners are installing a source distribution of python-gphoto2 and building it against a version of libgphoto2 installed on the runner.

I'm a bit worried about the 'no ltdl (for portable loading of camlibs)' bit in your libgphoto2 info, but it's present in both working and non-working versions so maybe not a problem. [Edit: no ltdl is common, ignore it.] Another difference is libusb0, for USB cameras on the failing system - libusb0 is known to be buggy, so installing libusb1 might be worth trying.

Other than that I'm out of ideas.

jim-easterbrook commented 1 year ago

I've managed to get one of my example scripts to generate a segfault on an Ubuntu 20.04 VM (as I happened to have one already set up) with python-gphoto2 v2.3.5. Using v2.3.4 gives a WARNING: gphoto2: (gp_port_usb_close [libusb.c:309]) Invalid parameters: 'port && port->pl->dh' is NULL/FALSE. message which might be relevant. (These are both using binary wheels from PyPI.)

mgineer85 commented 1 year ago

Glad you were able to reproduce on your side also. You think you can fix it? Let me know if you need further information or testing from my side.

jim-easterbrook commented 1 year ago

Since uninstalling and reinstalling python-gphoto2 a few times, and apt updating my rather old Ubuntu VM, I can no longer reproduce it. However, I've discovered that the auditwheel repair step in the binary wheel creation is copying the libgphoto2 and libgphoto2_port shared libraries to the directory it uses for system libraries, even though I'm already including them in the package data. This might lead to confusion about which version gets used, especially as libgphoto2 dynamically loads its camera and port libraries. (These don't get copied by auditwheel repair as it doesn't know about them.)

jim-easterbrook commented 1 year ago

Now I find that local builds of python-gphoto2 on my main openSUSE machine are also not using the "private" copies of libgphoto2 and libgphoto2_port included in the python package. The linker option -Wl -rpath,$ORIGIN/libs does not appear to do what I thought it should.

This might all be irrelevant, but it's one thing that is definitely wrong!

jim-easterbrook commented 1 year ago

OK, that was a red herring. The "private" copies are picked up as soon as the originals are deleted or moved. auditwheel repair renames the shared libraries to avoid that sort of problem.

jim-easterbrook commented 1 year ago

@mgrl One thing that would be useful to check is if you are doing a "source" or "binary" install of python-gphoto2. Using pip's --only-binary or --no-binary options will force one or the other and might be worth adding to your GitHub actions to ensure you always use the one you expect to use.

mgineer85 commented 1 year ago

I want to use the contained libgphoto as it is more convenient. I know that for v2.3.4 actually the wheel is used for python 3.9 and 3.10. Since for 3.11 is no wheel avail, I added dependencies now and the build from sources succeeds now also. For 2.3.5 it was always using the wheels, since on GitHub runner earlier were no dependencies to build from source installed.

jim-easterbrook commented 1 year ago

I've now set up an Ubuntu 22.04 VM (with minimal install). Installed pip with apt, then used pip to install python-gphoto2 (with --user option). I cannot get it to segfault. Versions are as follows:

jim@jim-VirtualBox:~$ python3 -m gphoto2
python-gphoto2 version: 2.3.5
libgphoto2 version: 2.5.30, standard camlibs, gcc, no ltdl, EXIF
libgphoto2_port version: 0.12.1, iolibs: disk ptpip serial usb usbdiskdirect usbscsi, gcc, no ltdl, EXIF, USB, serial without locking
python-gphoto2 examples: /home/jim/.local/lib/python3.10/site-packages/gphoto2/examples
jim-easterbrook commented 1 year ago

One thing I've found. Installing python-gphoto2 from source (i.e. using the locally installed libgphoto2) gets rid of the NULL port warning:

jim@jim-VirtualBox:~$ python3 -m gphoto2
python-gphoto2 version: 2.3.5
libgphoto2 version: 2.5.27, standard camlibs, gcc, ltdl, EXIF
libgphoto2_port version: 0.12.0, iolibs: disk ptpip serial usb1 usbdiskdirect usbscsi, gcc, ltdl, EXIF, USB, serial without locking
python-gphoto2 examples: /home/jim/.local/lib/python3.10/site-packages/gphoto2/examples
jim@jim-VirtualBox:~$ python3 /home/jim/.local/lib/python3.10/site-packages/gphoto2/examples/list-cameras.py 

Reinstalling the binary wheel uses a later version of libgphoto2, but brings the warning back:

jim@jim-VirtualBox:~$ pip install --user gphoto2 --force-reinstall
Collecting gphoto2
  Using cached gphoto2-2.3.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (11.0 MB)
Installing collected packages: gphoto2
  Attempting uninstall: gphoto2
    Found existing installation: gphoto2 2.3.5
    Uninstalling gphoto2-2.3.5:
      Successfully uninstalled gphoto2-2.3.5
Successfully installed gphoto2-2.3.5
jim@jim-VirtualBox:~$ python3 -m gphoto2
python-gphoto2 version: 2.3.5
libgphoto2 version: 2.5.30, standard camlibs, gcc, no ltdl, EXIF
libgphoto2_port version: 0.12.1, iolibs: disk ptpip serial usb usbdiskdirect usbscsi, gcc, no ltdl, EXIF, USB, serial without locking
python-gphoto2 examples: /home/jim/.local/lib/python3.10/site-packages/gphoto2/examples
jim@jim-VirtualBox:~$ python3 /home/jim/.local/lib/python3.10/site-packages/gphoto2/examples/list-cameras.py 
WARNING: gphoto2: (gp_port_usb_close [libusb.c:309]) Invalid parameters: 'port && port->pl->dh' is NULL/FALSE.

The binary wheel iolibs include usb but the locally built ones include usb1! I think that might be the problem.

jim-easterbrook commented 1 year ago

OK, I've built binary wheels using libusb1 and the NULL port warning is gone. If you'd like to try them you can download the set of wheels from the action (I assume - let me know if there's a permissions problem). I'll get a new release onto PyPI later today. https://github.com/jim-easterbrook/python-gphoto2/actions/runs/5585746541

jim-easterbrook commented 1 year ago

New release is on PyPI now.

mgineer85 commented 1 year ago

Tested v2.3.6 from pypi. Seems to work fine now! Thank you for fixing so quick! 😀

jim-easterbrook commented 1 year ago

Thank you for bringing the problem to my attention. I hadn't realised that libusb0 could be the cause of problems like this.

jim-easterbrook commented 1 year ago

I'm adding some unit tests to python-gphoto2 that might pick up problems like this in future. (Although using gphoto2's virtual camera won't test the actual USB driver.)

mgineer85 commented 1 year ago

Close it because resolved. Thx. One question: is it possible to choose the virtual interface in the pypi package for testing purposes without any installation in the system?

jim-easterbrook commented 1 year ago

Setting the environment variable VCAMERADIR to a directory with a JPG file in it should get libgphoto2 to use the vusb virtual camera driver, if it's been included in the libgphoto2 build (which none of the PyPI releases so far have). Also the virtual camera driver doesn't work in libgphoto2 v2.5.30. For my testing I'm using libgphoto2 from GitHub, built with the --enable-vusb configure option. The next PyPI release will follow a new release of gphoto2 and have all this sorted out.

mgineer85 commented 1 year ago

Awesome. Then I wait. Having to build stuff is to troublesome. I’d like to stick to a pretreated package. thx a lot!