Classic snaps and python

Just wanted to share some woes I recently suffered when using modules that depend on ctypes, and the problem at hand really is the implementation for find_library works in the ctypes.util module.

What happens in a nutshell is that that code runs ldconfig -p, this has two problems:

  1. We get anything in the ld cache, which means any system library as a result.
  2. It will never find anything inside $SNAP

By changing the implementation (could even just be a mapping of name -> libname for very strict and under control implementations) and setting things will get going successfully.

For illustration, this is the hacky fix I did in snapcraft to get things going http://paste.ubuntu.com/24312683/

If you are a victim of this you will see an OSError exception that looks like:

OSError: Could not locate nacl lib, searched for libsodium.so, libsodium.so.13, libsodium.so.10, libsodium.so.5, libsodium.so.4, and tweetnacl.so

And you might be confused because you might have libsodium.so inside $SNAP. This error can be masked the other way if you have it installed on the system and without notice, you’d be using that instance of the library.

2 Likes

Is there a clear symptom of the problem which might help people searching for it to find your solution here? Some telling error message or anything else along those lines?

1 Like

Yes actually, there is a bug, I’ll link to it and the final Exception

I’ve hit something very similar to this yesterday. Thank you for noting it here - it was helpful to have found this post.

I ended up hacking python-augeas in the code where it looks for the library. When inside a snap, I’ve hardcoded the path.

This can’t go upstream in its current state of course. Any suggestions on a proper fix? Perhaps the bug you referred to has more information. Could you link it please?

My workaround is as follows:

--- a/augeas/ffi.py
+++ b/augeas/ffi.py
@@ -1,3 +1,4 @@
+import os
 from cffi import FFI
 
 ffi = FFI()
@@ -39,7 +40,10 @@ void aug_close(augeas *aug);
 void free(void *);
 """)
 
-lib = ffi.dlopen("augeas")
+if os.getenv('SNAP'):
+    lib = ffi.dlopen(os.path.join(os.getenv('SNAP'), "usr/lib/x86_64-linux-gnu/libaugeas.so.0"))
+else:
+    lib = ffi.dlopen("augeas")
 
 if __name__ == "__main__":
     ffi.compile(verbose=True)

I stuck this modified version of python-augeas in a branch on GitHub and added as an additional part that installs first. Then it fulfills the later requirement for python-augeas so it gets used instead.