python and its dlopen implementation

[prev] [thread] [next] [lurker] [Date index for 2006/01/25]

From: Simon Wistow
Subject: python and its dlopen implementation
Date: 12:58 on 25 Jan 2006
It's a lovely sunny Wednesday. I recline, trendily, in my Herman Miller 
Aeron chair and take a sip from my Latte revelling in my meeja world 
comfort. 

I get a phone call.

The python wrapper round a C library I recently released a new version 
of is not working claiming that it can't find some symbols.

"Oh!", I chuckle, "They probably just didn't set the LD_LIBRARY_PATH 
right".

I investigate. Everything seems in order yet still these undefined 
symbol error messages are appearing.

"How rum!" I think, switching inexplicably from meeja-luvvy to circa 
1915 toff-about-town.

Even rummer is the fact that it's not *my* C library that's failing. 
It's not even the C library that my lib links to. It's the plugins for 
the second C library. In short, the situation looks like


    foo.py                                          OK
         - libfoo.so                                OK
                  - libbar.so                       OK
                          - libbar_plugin1.so       FAIL
                          - libbar_plugin2.so       FAIL
                          - libbar_plugin3.so       FAIL

And the plugins are failing because they can't find symbols in 
libbar.so. Which are there because nm says they are and it's in the 
LD_LIBRARY_PATH because libfoo.so is loading it.

I try gdb, I try Totalview. Nothing seems to explain the fact that this 
just shouldn't be happening. It's almost like the LD_LIBRARY_PATH is 
being clobbered between libbar.so and the plugins.

A cup of tea. And then a G&T for good measure.

Scratch my head.

No! It couldn't be.

Oh, yes it could.

Python, by default, dlopens its extensions which is sensible. And 
depending on a compile time flag it uses RTLD_NOW or RTLD_LAZY.

Which is fine. 

Except that means that symbols aren't propagated down through any 
further dlopens like, for example, the ones that libbar.so is doing to 
fetch its plugins. Both of those should be ORed against RTLD_GLOBAL 

I'm sure there are reasons why not doing this is the default and, to be 
fair, you can get that back by doing

    import dl
    import sys
    flags = sys.getdlopenflags()
    sys.setdlopenflags(flags | dl.RTLD_GLOBAL)


but this is "*HATES* software", not "Accept ugly workarounds as being 
acceptable software"

KEEEL THEM. KEEEL THEM ALLL.

Oh look, now I'm some sort of cliched Mexican Bandit Lord.

Bastards have turned me mad.



 



Generated at 18:00 on 31 Jan 2006 by mariachi 0.52