[unixODBC-support] Shared lib crash on load when linked with-lodbc or dlopen called
Stefan.Radman at CTBTO.ORG
Thu Mar 3 09:26:48 GMT 2005
> Let us know what the problem was.
Oh, yes. Please.
> -----Original Message-----
> From: unixodbc-support-bounces at easysoft.com
> [mailto:unixodbc-support-bounces at easysoft.com] On Behalf Of
> Martin J. Evans
> Sent: Thursday, 03 March, 2005 10:17
> To: Support for the unixODBC project
> Subject: RE: [unixODBC-support] Shared lib crash on load when
> linked with-lodbc or dlopen called
> A couple of suggestions to look at:
> o Is unixODBC built threaded with -D_REENTRANT and -pthread
> (the default) but
> your code is not? Reason I ask is that on some glibc
> systems I think the
> structure used by dlopen are different when built the two
> ways. This can
> causes crashes on unloading.
> o what arguments are you passing to dlopen? RTLD_GLOBAL?
> You need to be careful what flags you pass in case there
> are some symbol
> clashes. e.g.
> your code defines MYFUNC
> you dlopen unixODBC
> unixODBC dlopens driver
> The driver needs MYFUNC in a dependent shared object fred.so
> where MYFUNC in fred.so has different arguments
> Depending on what flag you pass to dlopen the MYFUNC in the
> ODBC driver can
> get resolved in your code or in the dependent fred.so.
> Solaris has RTLD_GROUP
> for this which forces resolution downwards in the chain
> from where the
> unresolved symbol is found. dlopen on my Linux machine does not have
> RTLD_GROUP but I think you could see the effect above if
> you used RTLD_GLOBAL.
> o Do any of the shared objects you are loading (or are loaded through
> dependencies) define _init or _fini entry points? The
> dynamic linker will
> call these on loading and unloading the libraries and they
> might contain
> something causing the problem you are seeing. If you use
> the debugging method
> below I thin you get to see which _init and _fini functions
> are called.
> What you can do is:
> export LD_DEBUG=files
> export LD_DEBUG_OUTPUT=/tmp/ld.out
> run your program
> Afterwards /tmp/ld.out will contain debugging from the
> dynamic linker showing
> you what files are loaded/unloaded etc. There are other
> options - just do:
> LD_DEBUG=help ls
> and you will see them.
> Let us know what the problem was.
> Martin J. Evans
> Easysoft Ltd, UK
> On 03-Mar-2005 Zachary Bedell wrote:
> > -----BEGIN PGP SIGNED MESSAGE-----
> > Hash: SHA1
> > Hello all!
> > I really hate to post this to the mailing list because I
> feel too much
> > like a begging newbie. It seems like I must be missing something
> > obvious, but after three days of solid hacking, I'm still
> in the dark.
> > That said, I *am* a newbie when it comes to ODBC as this is
> only the
> > second project I've tried with unixODBC. (The first
> project is working
> > pretty well now, so I know how to do something right.)
> > I'm working on porting some Windows ODBC code to run under Linux
> > (kernel 2.4, libc 2.3.4, gcc 3.3.4 on Gentoo with unixODBC
> > The code is part of a shared object that is loaded as a
> plugin to the
> > Helix DNA server from RealNetworks. The Windows version of
> this code
> > is known to work. I thought this would be an easy port job, but I
> > guess that's what I get for thinking...
> > The Windows code uses LoadLibrary to load odbc32.dll and
> > to get function pointers. My first attempt was to convert
> the function
> > pointer calls to direct calls and link with -lodbc. That compiled
> > fine, but as soon as Helix loaded the module, it would crash with
> > SIGCHLD. Linking that without -lodbc didn't crash Helix, but it of
> > course complained as soon as it tried to access any of the ODBC
> > functions since the symbols didn't resolve.
> > I switched to manually calling dlopen to load the library
> and dlsym to
> > get pointers to the various functions. I probably should
> have started
> > that way as it was much less work. A few macros to map the
> > from LoadLibrary, GetProcAddress, and FreeLibrary onto
> dlopen, dlsym,
> > and dlclose; and I was done. That way, the library loads
> > and properly queries the database. Unfortunately right after Helix
> > deconstructs the class, it SIGCHLD's again. I found that
> if I run with
> > the call to dlopen commented, the server does not crash.
> Also, if I
> > comment out all the function bodies and ONLY call dlopen, then the
> > server still crashes after deconstructing the last instance of the
> > class.
> > I've managed to narrow down the original cause of my
> crashes to the act
> > of loading the unixODBC libodbc.so. If I don't load the library, I
> > don't crash. If I do load the library, even if I don't do anything
> > else, I still crash. I've also tried using both FreeTDS
> and MyODBC as
> > the drivers with unixODBC. The behavior's the same with
> both, so I'm
> > pretty confident that rules out FreeTDS as the cause.
> > I'll try to describe as much as I can about the environment
> that I'm
> > calling unixODBC from, in case any of these details are helpful:
> > The code has a global void * that holds a handle returned
> from dlopen
> > and a number of global function pointers for the ODBC API
> > The .cpp file for this object contains static functions (not class
> > members) that call dlopen and dlsym before the first time the ODBC
> > functions are needed. The LoadODBCLibrary function is
> called each time
> > the database portion of the class is initialized, and each time it
> > checks to see if the global handle to the library is NULL. If the
> > handle is non-NULL, it does nothing as some previous invocation has
> > already loaded the library. I've confirmed (with printf's)
> that dlopen
> > is only called once.
> > The global function pointers survive multiple instantiations of the
> > class and dlclose is finally called when Helix sends a
> shutdown message
> > to the plugin (another static function defined by Helix's
> plugin API).
> > I've got the code filled up with printf's at the moment, and I've
> > confirmed that Helix is never sending the shutdown message and the
> > nothing is trying to call dlclose before the crash (that's as it
> > should be since Helix would ordinarily keep running and
> continue using
> > the ODBC library). I can also see that the object is created and
> > destroyed multiple times during Helix's startup routines
> without any
> > problem. The catch is that those startup routines don't
> load the ODBC
> > library. That happens later only when the database portion of the
> > class is init'ed. Once the library IS loaded, then once all the
> > instances of the class are released, Helix crashes. I've confirmed
> > using printf's in my code and with additional debugging
> message that
> > Helix produces that control has returned to Helix (outside of my
> > object) before it crashes. The deconstructor method of my class
> > completes and no other functions in my code are called
> between the end
> > of the deconstructor and the crash. There is a debug message from
> > Helix that announces it's deleting the Client object that
> was using my
> > code, and a few milliseconds later it crashes. The deconstructor
> > doesn't call dlclose nor touch the function pointers at all.
> > Up until the crash, the ODBC library is functioning
> correctly. It does
> > successfully query and return data from my MS SQL Server or MySQL.
> > So I feel like a heel begging for help here. The project
> in question
> > is only sort-of open source as you need to execute a clickwrap
> > agreement to get it. That said, I'm totally clueless and
> would REALLY
> > appreciate any debugging pointers that might help me track
> down what's
> > going on here. Is there anything magic I can do to debug
> what might be
> > happening in libodbc or elsewhere after my code is done?
> Is there any
> > code in the ODBC libraries that could execute "on its own"
> after all of
> > the various handles are released? I'll take anything at all!
> > Thanks in advance,
> > Zac Bedell
> unixODBC-support mailing list
> unixODBC-support at easysoft.com
More information about the unixODBC-support