Loading shared library twice - c

I'm trying to load a shared library in C twice:
lib1 = dlopen("mylib.so", RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);
lib2 = dlopen("mylib.so", RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);
What I want is that lib1 and lib2 have separate address spaces so that they can do different things. Currently, the only way I can achieve this is by copying mylib so that the code looks like this:
lib1 = dlopen("mylib.so", RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);
lib2 = dlopen("mylib2.so", RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);
In a limited scope this works fine for me. However, I have an application which uses the library a generic number of times which makes copying the library cumbersome.
Is there a better way to have a separate address space for each time the library is loaded?
EDIT:
I want to load the library multiple times as my application is processing a kind of message queue. The items in the message queue refer to the name of a shared library (e.g. mylib) and contain a set of data that shall be processed by the library. I want to process the MQ in a multithreading environment, running each call to the library's method in its own thread.
As long as the MQ contains the call to a library only once, everything is working as expected. However, when I have two items that use the same library, things start to get weird.

You need to use dlmopen to achieve this sort of isolation:
// No need for RTLD_LOCAL, not sure about RTLD_DEEPBIND
lib1 = dlmopen (LM_ID_NEWLM, "mylib.so", RTLD_LAZY | RTLD_DEEPBIND);

The whole idea of dynamically loading code is that you are thus able to share it, in particular with other processes. For that reason, I don't think that it is possible to really load the library twice.
There are ways around this though. One may be to fool the dynamic linker into loading it a second time. Copying the library is one way that you found already. I could imagine hard links to work, too.
However, I think it would be better if you worked with the flow here. I see two ways to achieve what I guess is your goal: Forking a separate process or creating a separate init function.
For the separate process, you just fork(), after setting up appropriate IPC mechanisms between parent and child instead of loading the library a second time. Since the fork creates a new process, it receives its own memory space and things remain separate. As IPC I'd suggest using some kind of middleware, like ZeroMQ, dbus or XMLRPC.
Creating a separate init function is the other option. For that, instead of creating the library's state as globals, you throw them together into a structure. Then, in that init function, you create an instance of that structure, set it up and returns its address. All other functions, which previously operated on the global state, now receive the address of that structure as additional (customary first) parameter. Instead of loading the library twice, you simple call the init function twice to set up separate environments.

Is there a better way to have a separate address space for each time the library is loaded?
Actually, a virtual address space belongs to a process (so to all threads inside it), not to a shared library (which uses several segments of that virtual address space).
For a process of pid 1234, use pmap(1) (as pmap 1234) or proc(5) (e.g. try cat /proc/1234/maps ...)
You really should avoid dlopen(3)-ing the same shared library "twice" (and this is difficult, on purpose; you could use symlinks and dlopen several symlinks to the same shared object, but you should not do this, for example because static data would be "loaded twice" and aftermath will happen). To avoid this happening, the dynamic loader uses reference counting techniques...
Read also Drepper's How to Write Shared Libraries
Is there a better way to have a separate address space for each time the library is loaded?
You then need different processes, each having its own virtual address space. You'll use inter-process communication : see pipe(7), fifo(7), socket(7), unix(7), shm_overview(7), sem_overview(7) etc...

Related

Is there a way to share a variable (within a shared lib) between processes?

I would like to initialize a complex variable within a shared library, but only once. Afterwards I would like to share the now initialized variable with all processes that are using this lib.
Example
Let's say the lib is called libgetx.so and it is having the functions
int get_variable_x() - which returns the value of a variable called x.
init_x(5) - which is initializing x
I would like to init x only once (maybe at loading of the lib) - imagine something costly, like parsing a config-file.
Now, everytime I call get_variable_x() from a process that is linked to the shared lib, I would like to be able to read out x. But without initializing it again (since it already in another process).
Is this possible?
I am not sure what exactly is happening in the system when you are calling a function from a shared lib from different processes, but it looks like they do not share the same space.
Actual Situation:
I am on Linux. I would like to parse a yaml config file and get the config values via a shared library instead of parsing the config file again and again. I am using yaml-pp and yaml-cpp-path for getting the values. It would then call e.g. get_config("something.id)to get theid` which is defined in the yaml file.
The specific answer of how to go about doing this would be platform-specific, but you want to look into whatever shared memory facilities your platform provides. In short, you'd set up a mutex or something equivalent and wait for the mutex to unlock.
Once the mutex unlocks, the exact order of steps depends on how shared memory on your platform works, but you'd need to create/attach to the memory segment, find out if some other process has created the segment already, and if not then write the shared data to it.
After all this is done, release the mutex and go about your merry way.

Using thread-safe libraries

I can think of two ways a thread-safe library can be used:
One is having a global instance of the library protected by a mutex, which is initialised by the main thread and used by worker threads, like so:
mutex g_lib_mutex;
lib_t g_lib;
thread:
lock(&g_lib_mutex);
/* use lib */
unlock(&g_lib_mutex);
main:
lib_init(&g_lib);
start_threads(thread);
lock(&g_lib_mutex);
/* use lib */
unlock(&g_lib_mutex);
join_threads();
lib_close(&g_lib);
The other, is for every thread to have a local instance of the library, something like this:
thread:
lib_t g_lib;
lib_init(&g_lib);
/* use lib */
lib_close(&g_lib);
main:
start_threads(thread);
lib_t g_lib;
lib_init(&g_lib);
/* use lib */
lib_close(&g_lib);
Which of these ways is more correct / preferable?
Do I need to protect library calls with a global mutex in both cases?
I was trying to use libmysql and POSIX message queues in a multi-threaded application when this question crossed my mind.
Generally, only initialize a library once. Remember, all threads happen in the same process' memory space, so whatever you do to any global variables in thread X is true for all threads. Library initialization should happen only once per process.
Now, whether library calls are thread safe or must be protected by mutexes is a question of your library. Modern libraries should have definite documentation on what functions you're allowed to call from multiple threads. If that info is missing you can either
assume the worst and encapsulate everything that changes something that the library deals with, or calls into the library, with a single global mutex, or
read the source code of the library to figure out what might go wrong where, introduce security measures (mutexes/conditions) accordingly, and make sure that no one uses a different version of the library (where things might be different), or
improve the documentation, send that patch to the upstream developers asking them to verify that what you document in thread-(un)safety is intentional and matches reality, (documentation patches are, for any project that I know of, always welcome) or
modify the library itself to be thread safe (making yourself a hero).

Remap shared library on a child process

Parent is forking a new child.
This child inherits the parent shared library libfoo.so
If I look at the child process memory map related to libfoo.so, the virtual mapping are the same of the parent (as it should, since doing a fork())
I would like to be able to remap the child shared library (libfoo.so), to a different virtual mapping, (which is of course different from the parent)
Do you have an idea ? or off-the-shelf solution for it ?
is it possible ?
It's generally impossible. Dynamic loader loads and relocates libraries on spawn and you shouldn't attempt calling it directly from running code.
Even in case you can somehow fit in the call of dynamic loader, it would like to start clean (meaning it will want to relocate itself, but it's already relocated…). It will also want to load and relocate all libraries, not just one of them.
So, simply speaking, there's no interface for doing this in Glibc and probably every other C library.
Then, there are also different formats of relocation information. In case of x86 and x86-64 it's RELA, meaning the relocations have explicit addends in separate table, and hence it's possible (in principle) to edit addresses again. But on ARM, the relocations are REL, meaning addends are implicit and are lost (overwritten) once you do the relocation.
You should look at dlopen and co. — maybe they'll fit your purpose.

Erlang NIF from single process storing structs in memory

Im writing an Erlang C NIF that will only be used by one Erlang process. I want to create a struct that will hold an array of pointers. I need this to exist in between the process' calls to the NIF.
What I need insight to is the proper way to do this approach from the Erlang NIF side of things. Im thinking of writing a struct outside of all the functions so its accessible to all. When I create it in one call to the NIF, and then come back and use it with another call to the NIF, it seems to work just fine.
Im worried that this could be because the process is staying local to the scheduling thread and therefore does not have to move the struct and underlying array in memory.
Should I be using erlang:memalloc from within a function and avoiding globals all together or, staying as is with global structs?
Possibly return a pointer to a single array containing all my data?
You could certainly return a pointer to a single array containing your data; to do that, look at ErlNifResourceType. You would pass this back to the calling erlang process, and it in turn would pass it back to you on subsequent NIF calls. This would ensure that only one thread was operating on your data at a time (assuming only one process had a copy of the resource; it's not something you want to share, especially if it contains pointers).
You could also encode it as an erlang list, but that would probably be very inefficient.
That being said, you can use shared memory from a NIF. For example, here's an ets-like database implemented as a NIF using shared data.
You just have to keep in mind that you're accessing shared resources. The NIF API provides thread creation, thread specific data, mutexes, conditions, and read/write locks. You can even send a message to an erlang process from a NIF-created thread (in the event of a long-running NIF call, this is actually how you'd want to implement it to prevent scheduling problems).
Given your requirements, you're probably better off using the ErlNifResource type rather than messing with multithreading and shared resource controls. Technically if you're only using one erlang process you could leave it as a global variable (read: shared resource) without any harmful side effects. That being said, things change, and you don't want to be the cause of someone's headache down the road when they try to use your code from multiple processes. Whichever method you wind up using, make sure it's thread safe.

How do I count the number of running threads (pthreads)?

If I search for counting the number of threads an application has, all the answers involve external programs like top. I want to count the threads within the application itself.
I can't add code at the point of thread creation because it happens inside an immutable library.
I can't read /proc.
It's a C/pthreads program running on a few different Unices.
If you can't read /proc you are a bit in trouble, unless your program communicate with another program which reads /proc
If you don't want to read /proc because of portability concerns, you might use a library which abstracts that a bit, like libproc does
You could write a tiny wrapper for pthread_create that counts created threads and link against that wrapper after you linked against the immutable library.
Use top -H. But chances are, if you can't read proc, top won't work anyway. If thats the case, there is no easy way and it would depend on your specific system.

Resources