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

OSError importing wand.image on Termux (missing glibc) #409

Closed
ioistired opened this issue Apr 25, 2019 · 3 comments
Closed

OSError importing wand.image on Termux (missing glibc) #409

ioistired opened this issue Apr 25, 2019 · 3 comments
Milestone

Comments

@ioistired
Copy link

On Termux, I get the following traceback:

>>> import wand.image
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File ".venv/lib/python3.7/site-packages/wand/image.py", line 19, in <module>
    from .api import libc, libmagick, library
  File ".venv/lib/python3.7/site-packages/wand/api.py", line 221, in <module>
    libc = ctypes.cdll.LoadLibrary('libc.so.6')
  File "/data/data/com.termux/files/usr/lib/python3.7/ctypes/__init__.py", line 434, in LoadLibrary
    return self._dlltype(name)
  File "/data/data/com.termux/files/usr/lib/python3.7/ctypes/__init__.py", line 356, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: dlopen failed: library "libc.so.6" not found

This makes sense as Termux does not provide glibc.

Wand version: 0.5.2
Python version: 3.7.3

The offending code appears to be here:

wand/wand/api.py

Lines 218 to 221 in 6f305a9

elif sys.platform.startswith(('dragonfly', 'freebsd')):
libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c'))
else:
libc = ctypes.cdll.LoadLibrary('libc.so.6')

Indeed, changing sys.platform to 'freebsd' and then running the import, does work. Is there any reason that the generic libc is only used on FreeBSD and DragonFly BSD? Perhaps ctypes.util.find_library('c') could be used every time? Or, maybe ImportError could be raised when an OSError is encountered here?

@emcconville
Copy link
Owner

We just need another elif for platforms using bionic, or create another loop...try...return method like wand.api.load_library().

Sadly, I do not have the time / resources to develop against that platform. But the second options can be something like...

diff --git a/wand/api.py b/wand/api.py
index 38e19bd..f955853 100644
--- a/wand/api.py
+++ b/wand/api.py
@@ -218,7 +218,14 @@ else:
     elif sys.platform.startswith(('dragonfly', 'freebsd')):
         libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c'))
     else:
-        libc = ctypes.cdll.LoadLibrary('libc.so.6')
+        libc_paths = ('libc.so.6', 'libc.so', 'libc.a',
+                      ctypes.util.find_library('c'))
+        for libc_path in libc_paths:
+            try:
+                libc = ctypes.cdll.LoadLibrary(libc_path)
+                break
+            except (IOError, OSError):
+                continue
     libc.fdopen.argtypes = [ctypes.c_int, ctypes.c_char_p]
     libc.fdopen.restype = ctypes.c_void_p
     libc.fflush.argtypes = [ctypes.c_void_p]

Let me know if the above suggested patch works, or if you know a way to identify bionic platform via standard Python modules.

@ioistired
Copy link
Author

That patch works for me.

#365 appears to also fix this issue, and seems to be cleaner and without an explicit test for BSD. Thoughts on using that approach?

@emcconville emcconville added this to the Wand 0.5.4 milestone Apr 25, 2019
@emcconville
Copy link
Owner

That patch works for me.

Cool.

Thoughts on using that approach?

I think that approach punts the problem down field, but suggests a few good points. I'll spend some time reworking the solution. Honestly, we only use libc for fopen & fflush, and already have a fallback in place -- if libc is not available. Might be worth reducing complexity.

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

No branches or pull requests

2 participants