View Single Post
Old Today, 02:16 AM   #5
xiatian
Connoisseur
xiatian began at the beginning.
 
Posts: 59
Karma: 10
Join Date: Oct 2018
Device: kindle
Quote:
Originally Posted by kovidgoyal View Post
This is what AI helped me and I think there maybe a fix for the next release.
Quote:
Thanks for the pointer. Traced this further and it doesn't look like
a plugin issue — here's what I found:

1. calibre-customize -l shows only built-in plugins, no third-party
plugins installed at all.

2. Scanned every .so file under /root/calibre for a compiled ELF
dependency on libxml2.so.2:

find /root/calibre -type f -name "*.so*" | while read f; do
readelf -d "$f" | grep -q "libxml2.so.2" && echo "$f"
done

-> no output. Also did a strings scan across every file in
/root/calibre for the literal string "libxml2.so.2" -> also
nothing found. So nothing is linking against it at the ELF level,
confirming what you said.

3. However, running this with calibre's own bundled python:

/root/calibre/calibre-debug -c "import ctypes.util; print(ctypes.util.find_library('xml2'))"

returns: libxml2.so.2 (the system one, not calibre's bundled
libxml2.so.16)

So it looks like html5-parser is locating libxml2 at runtime via
ctypes.util.find_library() / dlopen rather than a compiled ELF NEEDED
dependency — which is why it doesn't show up in readelf or strings.
find_library() resolves through the system's ldconfig cache, which
only knows about whatever libxml2 the OS has registered — in this
case the system's own libxml2.so.2. It then tries to dlopen that
exact filename; the dynamic linker checks calibre's own lib dir first
(as seen in the LD_DEBUG trace) but finds no file by that name there
(calibre ships libxml2.so.16 under the new SONAME), so it falls
through to the system's copy instead. lxml, by contrast, loads
libxml2.so.16 directly and correctly picks up calibre's bundled copy.
End result: two different libxml2 versions loaded in the same
process.

I also tested this on a second, completely unrelated Debian 12 server
with a different software stack, and got the exact same error. So
it's not tied to any specific package pulling in libxml2 — the common
factor is simply that it's a Debian 12 host, and Debian 12's repo
still ships libxml2 2.9.14 under the old SONAME (libxml2.so.2), while
calibre's own bundled libxml2 has moved to the new SONAME (.so.16).
Given how many common packages transitively depend on libxml2, most
Debian 12 installs probably have some libxml2.so.2 registered in
ldconfig one way or another, so any Debian 12 host running the
official calibre binary seems likely to hit this.

As for a possible fix, I can see two independent ways to close this
gap (either one alone would probably be enough):

1. On the html5-parser side: instead of relying on
ctypes.util.find_library('xml2') (which resolves through the
system's ldconfig cache and has no awareness of calibre's own
bundled lib directory), it could resolve the libxml2 path the same
way lxml does — e.g. reuse the same shared library lxml already
loaded, or at least restrict the search to calibre's own lib dir
before falling back to a system-wide lookup.

2. On the calibre packaging side: since the bundled libxml2 SONAME
changed from .so.2 to .so.16 in this build, shipping a compat
symlink alongside it (libxml2.so.2 -> libxml2.so.16, inside
calibre's own lib dir) would make html5-parser's existing
find_library()-based lookup resolve correctly without any code
change.

For now I've applied the workaround you suggested:

ln -s libxml2.so.16 /root/calibre/lib/libxml2.so.2

which resolves it fine. Just wanted to share the fuller trace in case
it's useful.
xiatian is online now   Reply With Quote