Sharing data between users of a shared-library - c++

I have a shared library say foo.so which contains a function called initialize(). There are multiple executables that open foo.so and each calls initialize(). I would like initialize() to check if it has already been called by another executable and if so do nothing. What's the best way of sharing this information between these processes? Is there some special facility to share such information or do I need to use standard IPC?

Create a file /var/db/mylibname. If open() returns an error saying that the file already exists, then your library was initialized.
It'll require to add atexit() handler that will remove the file when process exits. Atexit must be initialized only if open() returns success.
UPDATE:
If resources must be initialized only once and if they (resources) don't depend on the existence of any process that uses the library at the time, then it's better to create file in /var/run directory (so that it is cleaned up after system reboot) and forget about atexit().

You need to use standard IPC. Memory mapping comes to mind, but first decide whether you want initialization per user and per machine.

Related

Calling shared libraries without releasing the memory

In Ubuntu 14.04, I have a C++ API as a shared library which I am opening using dlopen, and then creating pointers to functions using dlsym. One of these functions CloseAPI releases the API from memory. Here is the syntax:
void* APIhandle = dlopen("Kinova.API.USBCommandLayerUbuntu.so", RTLD_NOW|RTLD_GLOBAL);
int (*CloseAPI) = (int (*)()) dlsym(APIhandle,"CloseAPI");
If I ensure that during my code, the CloseAPI function is always called before the main function returns, then everything seems fine, and I can run the program again the next time. However, if I Ctrl-C and interrupt the program before it has had time to call CloseAPI, then on the next time I run the program, I get a return error whenever I call any of the API functions. I have no documentation saying what this error is, but my intuition is that there is some sort of lock on the library from the previous run of the program. The only thing that allows me to run the program again, is to restart my machine. Logging in and out does not work.
So, my questions are:
1) If my library is a shared library, why am I getting this error when I would have thought a shared library can be loaded by more than one program simultaneously?
2) How can I resolve this issue if I am going to be expecting Ctrl-C to be happening often, without being able to call CloseAPI?
So, if you do use this api correctly then it requires you to do proper clean up after use (which is not really user friendly).
First of all, if you really need to use Ctrl-C, allow program to end properly on this signal: Is destructor called if SIGINT or SIGSTP issued?
Then use a technique with a stack object containing a resource pointer (to a CloseAPI function in this case). Then make sure this object will call CloseAPI in his destructor (you may want to check if CloseAPI wasn't called before). See more in "Effective C++, Chapter 3: Resource Management".
That it, even if you don't call CloseAPI, pointer container will do it for you.
p.s. you should considering doing it even if you're not going to use Ctrl-C. Imagine exception occurred and your program has to be stopped: then you should be sure you don't leave OS in an undefined state.

Call external function(from one exe to another)

Lets say the process 1 is the main process and the process 2 is the target process(i can't edit it by the way), i want to be able to call a function from the process 2 in the process 1, anyone have a nice way to do that?I was thinking in inject a dll with exports that calls that function and use GetProcAddress externally...Is that possible?Is that the best way to do it?
Thanks for the time.
The title and body of your question ask two subtly different questions.
Having one executable call a function that's contained in another executable is quite easy, at least if the name of the function in question has been exported. You can use LoadLibrary to load an executable just like you would a DLL, then use GetProcAddress to get the address of the function you want to call, and call it normally. Keep in mind, however, that the function may not work correctly without other initialization that happens before it's called inside its own executable.
Calling a function in the context of another process (not just in another executable) is considerably more work. The basic idea is to have a function that makes the call and (for example) writes a result to some memory shared with the process making the call. You then use CreateRemoteThread to have that function execute in the context of the process containing the function you need to call.
If the target process has been written to support it there are other methods such as COM that are intended to support this type of capability much more cleanly. They're generally preferable if available.

C++: DLL with memory mapped file

I have an DLL that might get called by multiple applications at the same time.
This DLL memory-maps a file.
I have 2 questions:
1) Each application will create its own instance of the DLL, right?
And thus, the file will be memory-mapped multiple times
2) If this is true, I don't understand what is happening here:
a) Application A calls the DLL.
b) Application B calls the DLL.
c) I quit application A, and the DLL will unmap the file.
d) Application B calls the DLL, and the memory-mapped file is not available anymore, and the call fails.
I don't understand this.
Does anybody do?
Thank you.
This happens because your assumption from 1) is false. A dll is by definition shared; both applications are using the same dll instance, so when you release the file in one application, it won't be available to the others.
To get around your issue, you should implement some reference counting mechanism in order to unmap the file only when no process is using it.
Edit: #sumeet is right. Each process has its own address space; when two processes load the same dll, they might share its read-only data for increased efficiency, but their writable data is local to each process. Nevertheless, a memory-mapped file is a kernel object, like semaphores, pipes and shared memory. Thus, if you unmap it in a process, you unmap it for all.
Edit2: From MSDN (Remarks section):
Multiple processes can share a view of the same file by either using a
single shared file mapping object or creating separate file mapping
objects backed by the same file. A single file mapping object can be
shared by multiple processes through inheriting the handle at process
creation, duplicating the handle, or opening the file mapping object
by name. For more information, see the CreateProcess, DuplicateHandle
and OpenFileMapping functions.
[...]
Mapped views of a file mapping object maintain internal references to
the object, and a file mapping object does not close until all
references to it are released. Therefore, to fully close a file
mapping object, an application must unmap all mapped views of the file
mapping object by calling UnmapViewOfFile and close the file mapping
object handle by calling CloseHandle. These functions can be called in
any order.
First of all, from the first paragraph, how is each app initializing the view?
From the second paragraph, I gather that calling UnmapViewofFile and CloseHandle from each app will release all references to the memory file, and then Windows will automatically release the associated resources (i.e. he keeps the reference count, you don't need to do it).
Post your memory mapping initialization and shutdown code for both apps.

Converting a string into a function in c++

I have been looking for a way to dynamically load functions into c++ for some time now, and I think I have finally figure it out. Here is the plan:
Pass the function as a string into C++ (via a socket connection, a file, or something).
Write the string into file.
Have the C++ program compile the file and execute it. If there are any errors, catch them and return it.
Have the newly executed program with the new function pass the memory location of the function to the currently running program.
Save the location of the function to a function pointer variable (the function will always have the same return type and arguments, so
this simplifies the declaration of the pointer).
Run the new function with the function pointer.
The issue is that after step 4, I do not want to keep the new program running since if I do this very often, many running programs will suck up threads. Is there some way to close the new program, but preserve the memory location where the new function is stored? I do not want it being overwritten or made available to other programs while it is still in use.
If you guys have any suggestions for the other steps as well, that would be appreciated as well. There might be other libraries that do things similar to this, and it is fine to recommend them, but this is the approach I want to look into — if not for the accomplishment of it, then for the knowledge of knowing how to do so.
Edit: I am aware of dynamically linked libraries. This is something I am largely looking into to gain a better understanding of how things work in C++.
I can't see how this can work. When you run the new program it'll be a separate process and so any addresses in its process space have no meaning in the original process.
And not just that, but the code you want to call doesn't even exist in the original process, so there's no way to call it in the original process.
As Nick says in his answer, you need either a DLL/shared library or you have to set up some form of interprocess communication so the original process can send data to the new process to be operated on by the function in question and then sent back to the original process.
How about a Dynamic Link Library?
These can be linked/unlinked/replaced at runtime.
Or, if you really want to communicated between processes, you could use a named pipe.
edit- you can also create named shared memory.
for the step 4. we can't directly pass the memory location(address) from one process to another process because the two process use the different virtual memory space. One process can't use memory in other process.
So you need create a shared memory through two processes. and copy your function to this memory, then you can close the newly process.
for shared memory, if in windows, looks Creating Named Shared Memory
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366551(v=vs.85).aspx
after that, you still create another memory space to copy function to it again.
The idea is that the normal memory allocated only has read/write properties, if execute the programmer on it, the CPU will generate the exception.
So, if in windows, you need use VirtualAlloc to allocate the memory with the flag,PAGE_EXECUTE_READWRITE (http://msdn.microsoft.com/en-us/library/windows/desktop/aa366887(v=vs.85).aspx)
void* address = NULL;
address= VirtualAlloc(NULL,
sizeof(emitcode),
MEM_COMMIT|MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
After copy the function to address, you can call the function in address, but need be very careful to keep the stack balance.
Dynamic library are best suited for your problem. Also forget about launching a different process, it's another problem by itself, but in addition to the post above, provided that you did the virtual alloc correctly, just call your function within the same "loadder", then you shouldn't have to worry since you will be running the same RAM size bound stack.
The real problems are:
1 - Compiling the function you want to load, offline from the main program.
2 - Extract the relevant code from the binary produced by the compiler.
3 - Load the string.
1 and 2 require deep understanding of the entire compiler suite, including compiler flag options, linker, etc ... not just the IDE's push buttons ...
If you are OK, with 1 and 2, you should know why using a std::string or anything but pure char *, is an harmfull.
I could continue the entire story but it definitely deserve it's book, since this is Hacker/Cracker way of doing things I strongly recommand to the normal user the use of dynamic library, this is why they exists.
Usually we call this code injection ...
Basically it is forbidden by any modern operating system to access something for exceution after the initial loading has been done for sake of security, so we must fall back to OS wide validated dynamic libraries.
That's said, one you have valid compiled code, if you realy want to achieve that effect you must load your function into memory then define it as executable ( clear the NX bit ) in a system specific way.
But let's be clear, your function must be code position independant and you have no help from the dynamic linker in order to resolve symbol ... that's the hard part of the job.

Load a DLL More Than Once?

I'm using the LoadLibrary function to load a DLL in Windows. My question is this: If I call this method more than once for the same DLL, do I get handles to different instances of the DLL, or will they all refer to the same instance?
Additionally, how does this behaviour correlate to Linux SO files, is it the same or completely different, and what assumptions can I make in this regard? Thanks.
The MSDN documentation states:
The system maintains a per-process reference count on all loaded
modules. Calling LoadLibrary increments the reference count. Calling
the FreeLibrary or FreeLibraryAndExitThread function decrements the
reference count. The system unloads a module when its reference count
reaches zero or when the process terminates (regardless of the
reference count).
So it would appear that loading the module more than once (without matching calls to FreeLibrary) will return the same handle.
If the DLL is already loaded, LoadLibrary will simply return the address of the library in memory. However, DllMain is not called again with DLL_PROCESS_ATTACH when the second load is attempted. Handles in the sense of libraries are just memory locations, so the value you get the second time around should be the same as the first.
As far as linux SO files go, I don't see why they would load twice either. However, someone else will have to weigh in on this to give you a proper answer.
For Linux shared objects, from the dlopen(3) manpage:
If the same library is loaded again with dlopen(), the same file
handle is returned. The dl library maintains reference counts for
library handles, so a dynamic library is not deallocated until
dlclose() has been called on it as many times as dlopen() has
succeeded on it. The _init() routine, if present, is only called once.
But a subsequent call with RTLD_NOW may force symbol resolution for a
library earlier loaded with RTLD_LAZY.