Home > Software design >  How to load multiple shared libraries that are physical copies
How to load multiple shared libraries that are physical copies

Time:07-21

Background

We have a c library made for communicating with devices. 1 library can communicate with only 1 device. This library also creates a log file when it is inited. We now have a new project that needs to communicate to 30 devices at once.

Problem

This new project is in c 20 and will run on linux, we want to be able to load 30 of these libraries into the program so i have made 30 copies of this .so file what has no hard linking and has its names increment like mylib_0.so, mylib_1.so, ect.

There are other questions that are similar to this like

  1. Loading multiple copies of a shared library
  2. Load multiple copies of a shared library

Both suggesting to use

dlmopen(LM_ID_NEWLM, "/path/to/library.so", RTLD_NOW);

as the solution but when i try to do this, it seems to be going up to 10 and then it stops. I know this because each lib will create its own log file when inited correctly and i only see 10 log files created and also the dlmopen call returns null after the 10th call.

I also tried using the RTLD_LOCAL flag in the dlopen call but that makes it always fail.

Details

The architecture of this new project is such that we have a lib loader that will load all the API calls of the lib, we have this loader as a class and a master that can create instances of this loader object. There are no unique threads per loader as the libs already use threads and having so many loaded, we are conserving our thread resources as much as possible.

Question

How can i load copies of the same so files to 30 and maybe more instances?

Update 1

As suggested by Jakob Stark, i used dlerror and got the message of: /lib/x86_64-linux-gnu/libc.so.6: cannot allocate memory in static TLS block when using dlmopen on the 10th call.

Also, turns out i was using dlopen wrong, i now do this:

dlopen("/path/to/library.so", RTLD_NOW | RTLD_LOCAL);

If i do this, the dlopen seems to be called 30 times but i only see 1 log file with all 30 entries in them. I presume what is happening here is that dlopen is recognising that the .so is already loaded and returning true for it, making there be only one .so loaded.

Is it possible to make the .so's different enough so that dlopen thinks they are different .so files?

CodePudding user response:

The function dlmopen(LM_ID_NEWLM,...) loads the shared library into a new namespace every time. That means that each new instance of the library pulls in some standard libraries like for example libc.so. I could not find an answer, why in your case exactly 10 was the limit, but the manual says:

The glibc implementation supports a maximum of 16 namespaces.

Probably something different went wrong with the thread local storage, but we can already conclude, that using dlmopen with new namespaces is not the way to go here.


That leaves us with the plain dlopen() function. If one tries to load the same library twice, one gets the same handle and twice, which is generally a good thing, as a shared library is meant to be shared. It is however not what we want here.

The most promising solution I can come up with is loading the same library under different names. Symlinks won't work because dlopen() follows them and ends up at the exactly same file. The trick here is to use hardlinks. If your library is called mylib.so you can make several hardlinks using ln:

for i in {0..29}; do ln mylib.so mylib$i.so ; done

Now in your program you open them all by using e.g.

dlopen("mylib0.so", RTLD_NOW);

You will get different instances in the same namespace, with almost no additional disk space used by the different hardlinks.

CodePudding user response:

One common solution to this type of problems is to wrap the library in a separate helper process, which communicates with the main process via IPC. in Linux you can probably use popen for that.

On the C side, you replace the C object representing the device with a stub class implementing the same interface. Since this stub just holds an IPC handle, there's no problem in having 30 copies.

  • Related