Hook function to shared library unloading - linux

I want to add hook function, which will be called when shared library is unloaded. Library is linked on complitaion. Is it possible to do such thing? Maybe gcc has flag for it?
I saw similar solution for loading library on runtime, but it doesn't meet my expectations.

For Linux systems, the dlopen()/dlclose() man page explains how to add such a function to your library:
Initialization and finalization functions
Shared objects may export functions using the __attribute__((constructor)) and
__attribute__((destructor)) function attributes. Constructor functions are executed before dlopen() returns, and destructor
functions are executed before dlclose() returns. A shared object may
export multiple constructors and destructors, and priorities can be
associated with each function to determine the
order in which they are executed. See the gcc info pages (under "Function attributes") for further information.
An older method of (partially) achieving the same result is via
the use of two special symbols recognized by the linker: _init and
_fini. If a dynamically loaded shared object exports a routine named _init(), then that code is executed after loading a shared
object, before dlopen() returns. If the shared object exports a
routine named _fini(), then that routine is called just before the
object is unloaded. In this case, one must avoid linking against the
system startup files, which contain default versions of these files;
this can be done by using the gcc(1) -nostartfiles command-line
option.
Use of _init and _fini is now deprecated in favor of the
aforementioned constructors and destructors, which among other
advantages, permit multiple initialization and finalization
functions to be
defined.

Solaris and GNU/Linux support the LD_AUDIT interface in their dynamic linkers. You need to load an auditor module which implements the la_objclose callback function:
Runtime Linker Auditing Interface
The implementation can be as simple as this:
unsigned int
la_objclose (uintptr_t *cookie)
{
printf ("objclose\n");
return 0;
}
In order to determine which object is being closed, you also need to implement la_objsearch (and possibly la_objopen), to establish a cookie value which somehow refers to the information you need at close time (you could store a pointer to a heap-allocated struct in the cookie, for example).

Related

can pthread_mutexattr_setrobust apply to pthread_rwlock_t?

the robustness of mutex is very important to my program since it can handle the case when a process died without releasing the mutex.
But according to the document, pthread_mutexattr_setrobust only apply to pthread_mutex_t, instead of pthread_rwlock_t, is there any approach to set the robustness of pthread_rwlock_t? Or its implementation is robust by default?
according to the document, pthread_mutexattr_setrobust only apply to pthread_mutex_t
More precisely, pthread_mutexattr_setrobust() sets a property of a pthread_mutexattr_t object, and these are used (only) for configuring objects of type pthread_mutex_t. This happens at initialization of the mutex via pthread_mutex_init().
The corresponding initialization function for read/write locks is pthread_rwlock_init(), and its documentation shows that the corresponding attribute object type, accepted by that function, is pthread_rwlockattr_t. Implementations may provide whatever properties they like as extensions, but the only one specified for this type by the current version of POSIX is pshared. Thus no, there is no (portable) robustness option for pthreads read/write locks.

What happens to the thread spawned by a shared library, upon dlclose

This is the scenario:
I have an application (main.exe) which dynamically loads a library libA.so using dlopen(). libA.so has dependency on another library libB.so.
Now libB.so has a constructor that spawns a thread (in detached state) and blocks on reading from a named pipe.
What happens to the thread , when libA.so is unloaded using dlclose() - (i assume this will unload libB.so as well)?.
I get segmentation fault in the thread after the dlclose(libA.so).
Pseudo code:
main.c (main.exe):
handle = dlopen(libA.so)
// function calls
dlclose(handle)
libA.so depends on libB.so
b.c (libB.so):
__attribute_constructor__void start() {
pthread_create(ThreadFunction)
void ThreadFunction() {
while(1) {
fd = open("path_to_pipe", READONLY)
read(fd, buffer, size)
//Process the content
}
Unloading a shared library which is still in use is Undefined Behaviour. Calling dlclose() on a handle is a declaration that neither the functions nor the data objects provided through that handle are still required.
There is no way for dlclose() to verify this fact. If you still have a pointer to a function or data object in the loadable module, those pointers become invalid and may not be used. If there is a pointer into a loaded function on the call stack of any thread -- which will be the case if the thread is waiting on a file descriptor -- then that thread may not return into that call frame. (Longjmp to a prior frame might work, if the stack can be unwound without reference to the unloaded module. That will likely work in C, but throwing a C++ exception to escape from an unloaded function is likely to fail.
Congratulations - you've rediscovered that a non-nop dlclose implementation is fundamentally unsafe. The C language makes no provision for code or pseudo-static-storage data whose lifetime is anything other than the whole lifetime of the program, and in general library code cannot be safely removed since there are all sorts of ways that references to it may have leaked and still be reachable. You've actually found an exceptionally good example; common implementations attempt to catch and "fix" leaks via atexit and such by running the handlers at dlclose time, but there doesn't seem to be any way to catch and fix a thread left running.
As a workaround, there is a special ELF flag you can set by passing -Wl,-z,nodelete when linking the shared library libB.so (or libA.so if that's more convenient, e.g. if you don't have control over how libB.so is linked) that will prevent it from being unloaded by dlclose. Unfortunately, this design is backwards. Unloading is fundamentally unsafe unless a library is specifically written to be safe against unloading, so the default should be "nodelete" with an explicit option required to make unloading possible. Unfortunately there's little chance this will ever be fixed.
Another way to prevent unloading is have a constructor call dlopen on itself to leak a reference, so that the reference count will always be positive and dlclose will do nothing.

C++11 thread safe singleton using lambda and call_once: main function (g++, clang++, Ubuntu 14.04)

All!
I am new to C++11 and many of its features.
I am looking for a C++11 (non boost) implementation of a thread safe singleton, using lambda and call_once (Sorry... I have no rights to include the call_once tag in the post).
I have investigated quite a lot (I am using g++ (4.8, 5.x, 6.2), clang++3.8, Ubuntu 14.04, trying to avoid using boost), and I have found the following links:
http://www.nuonsoft.com/blog/2012/10/21/implementing-a-thread-safe-singleton-with-c11/comment-page-1/
http://silviuardelean.ro/2012/06/05/few-singleton-approaches/ (which seems to be very similar to the previous one, but it is more complete, and provides at the end its own implementation).
But: I am facing these problems with the mentioned implementations: Or I am writing a wrong implementation of main function (probable), or there are mistakes in the posted codes (less probable), but I am receiving different compiling / linking errors (or both things at the same time, of course...).
Similar happens with following code, which seems to compile according to comments (but this one does not use lambda, neither call_once):
How to ensure std::call_once really is only called once (In this case, it compiles fine, but throws the following error in runtime):
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
Aborted (core dumped)
So, could you help me, please, with the correct way to call the getInstance() in the main function, to get one (and only one object) and then, how to call other functions that I might include in the Singleton? (Something like: Singleton::getInstance()->myFx(x, y, z);?
(Note: I have also found several references in StackOverflow, which are resolved as "thread safe", but there are similar implementations in other StackOverflow posts and other Internet places which are not considered "thread safe"; here are a few example of both (these do not use lambda) ):
Thread-safe singleton in C++11
c++ singleton implementation STL thread safe
Thread safe singleton in C++
Thread safe singleton implementation in C++
Thread safe lazy construction of a singleton in C++
Finally, I will appreciate very much if you can suggest to me the best books to study about these subjects. Thanks in advance!!
I just ran across this issue. In my case, I needed to add -lpthread to my compilation options.
Implementing a singleton with a static variable as e. g. suggested by Thread safe singleton implementation in C++ is thread safe with C++11. With C++11 the initialization of static variables is defined to happen on
exactly one thread, and no other threads will proceed until that initialization is complete. (I can also backup that with problems we recently had on an embedded platform when we used call_once to implement a singleton and it worked after we returned to the "classic" singleton implementation with the static variable.)
ISO/IEC 14882:2011 defines in §3.6.2 e. g. that
Static initialization shall be performed before any dynamic initialization takes place.
and as part of §6.7:
The zero-initialization (8.5) of all block-scope variables with static
storage duration (3.7.1) or thread storage duration (3.7.2) is
performed before any other initialization takes place.
(See also this answer)
A very good book I can recommend is "C++ Concurrency in Action" by A. Williams. (As part of Chapter 3 call_once and the Singleton pattern is discussed - that is why I know that the "classic Singleton" is thread safe since C++11.)

Is it safe to call dlclose(NULL)?

I experience a crash when I pass a null pointer to dlclose.
Should I check for null before calling dlclose?
POSIX tells nothing about this:
http://pubs.opengroup.org/onlinepubs/7908799/xsh/dlclose.html
Is it undefined behaviour or a bug in dlclose implementation?
This is tricky. POSIX states that
if handle does not refer to an open object, dlclose() returns a non-zero value
from which you could infer that it should detect, for an arbitrary pointer, whether that pointer refers to an open object. The Linux/Glibc version apparently does no such check, so you'll want to check for NULL yourself.
[Aside, the Linux manpage isn't very helpful either. It's quite implicit about libdl functions' behavior, deferring to POSIX without very clearly claiming conformance.]
It also says nothing about being accepting a NULL and not crashing. We can assume from your test that it doesn't do an explicit NULL check, and it does need to use the pointer somehow to perform the closing action … so there you have it.
Following the malloc/free convention (1), it is a bug. If it follows the fopen/fclose convention (2) it is not. So if there is a bug, it is in the standard because it lacks convention for dealing with zombies.
Convention (1) works well with C++11 move semantics
Convention (2) leaves more responsibility to the caller. In particular, a dtor must explicitly check for null if a move operation has been done.
I think this is something that should be revised for an upcoming POSIX revision in order to avoid confusion.
Update
I found from this answer https://stackoverflow.com/a/6277781/877329, and then reading man pthread_join that you can call pthread_join with an invalid tid, supporting the malloc/free convension. Another issue I have found with the dynamic loader interface is that it does not use the standard error handling system, but has its own dlerrorfunction.

How does a portable Thread Specific Storage Mechanism's Naming Scheme Generate Thread Relative Unique Identifiers?

A portable thread specific storage reference/identity mechanism, of which boost/thread/tss.hpp is an instance, needs a way to generate a unique keys for itself. This key is unique in the scope of a thread, and is subsequently used to retrieve the object it references. This mechanism is used in code written in a thread neutral manner.
Since boost is a portable example of this concept, how specifically does such a mechanism work ?
Boost thread is portable to the pthread threading library (for unix) and the windows win32 low-level-API's. The library allows a reference to be created which is unique in each thread of execution. The global C API errno is presented as an example of this concept in Boost's documentation.
Ignore If you Want -- it's just a trace through the source code finding the function of interest
The crux of the matter begins in [boost]/boost/thread/tss.hpp with the get function of thread_specific_ptr and the reset function -- i.e., the aquisition and the destruction, respectively, of the object referenced. Note: the data object is not placed in the reference of thread_specific_ptr's ctor, or destroyed by the dtor. The get and reset function call set_tss_data and get_tss_data. Focusing just on the setting aspect of the functionality, the important function call, get_current_thread_data, indirects via the cpp file [boost]/libs/thread/src/[libname]/thread.cpp via a chain of function calls. In get_current_thread_data there is a function call create_current_thread_tls_key and this is the function that will create a unique identifier for the thread_specific_ptr object.
create_current_thread_tls_key calls TlsAlloc() on win32 (link) and pthread_key_create for pthread (link). These calls assure that upon initialization of the ptr, the ptr receives a unique identifier usable in an API-specific manner to retrieve the object's data. The specific threading API uses the thread-id (context specific and resolved by the library itself) and the object identifier to return the object specific to the context of a certain thread.

Resources