Can destruction order be controlled across dynamic libraries? - c++

I am encountering an issue where my library is crashing due to executable that loads me calling my function after main exits. I'm wondering - can I control the lifecycle of my globals to not be destroyed until (and if) my library gets unloaded? I understand what I'm asking.
Basically, the executable looks something like this (roughly):
struct MyLibController
{
void *libhandle;
void (*function)() myLibFunction;
~MyLibController()
{
myLibFunction(); // Call to my library's exported function
dlclose(libhandle);
}
};
std::shared_ptr<MyLibController> globalPtr;
int main(int argc, const char **argv)
{
globalPtr = std::make_shared<MyLibController>();
// initializing globalPtr to dlopen my library, map function ptrs, etc.
// do some work with my library
return 0;
}
I have absolutely no control over the code in this executable.
My library code look something like this:
SomeType globalObject;
// Exported function via c interface in my library
void myLibFunction()
{
// crash occurs globalObject is used after executable's main function exits
globalObject.someFunction();
// do some work
}
I have a lot of control over the library code - but this is a simple example. The Sometype globalObject is very necessary (suppose that it's a mutex, used to sync myLibFunction and a bunch of others).
I'd like to ensure that my globalObject is valid even after executable's main function exits. Is this possible? If so, how?
P.S. I am aware that I can dynamically allocate the globalObject and leak it, which resolves the crash. It feels wrong though, and I don't want to sign off on it.

You can register for a callback when the main() returns using std::atexit(): http://en.cppreference.com/w/cpp/utility/program/atexit
For example, when your library is loaded, use atexit() to register, then when that callback fires, set a flag for yourself that you check before trying to do anything else. If the flag is set, ignore any other actions from the caller, because the program is shutting down.

Your best bet is to make your global object a reference counted singleton of some sort. Then update your interface to instantiate an object from your loaded library. This object can then grab a reference to the global object during construction, and thus only releases it after it has been destroyed. The global variable itself would also merely have a reference, thus during the dlclose() process the global reference would be released, but your object would still have a reference until it is destroyed.

#o11c's comment provided a working solution:
Using attribute((constructor)) and attribute((destructor))
allows you to specify a priority
In other words, I can have the control over lifecycle of my variables despite binary's main function exiting (I just have to dynamically allocate them and free them).

Related

How to use a mutex/critical section within a member function inside a DLL

I'm creating a COM class (with ATL) that resides inside a DLL. For one of my member functions, depending on certain conditions, I'd like to potentially use a third-party library (Adobe's XMP SDK), which must be initialized and terminated. So basically, I'll have a member function which looks sort of like this:
void CMyClass::MyMemberFunction()
{
SXMPMeta::Initialize();
// ...
SXMPMeta::Terminate();
}
Now according to the Adobe XMP library docs,
You must call the initialization and termination functions in a
single-threaded manner . . . .
Meanwhile, I believe that File Explorer may create multiple instances of my class on separate threads. So if I understand things correctly, it sounds like I'll have a critical section and I'll need to use mutexes around the library initialization and termination (but please correct me if that's wrong).
I'm unclear on how to go about this. I wasn't sure if I should use one of the ATL critical section classes or perhaps CRITICAL_SECTION. CRITICAL_SECTION seemed like a nice option, but the example shows it being initialized in main(). What happens if you're in a DLL? I'd prefer not to start messing with DllMain(). Any help or thoughts would be appreciated.
Per Gem's suggestion, I tried the following:
struct XMPLibraryInitializer
{
XMPLibraryInitializer()
{
// Initialize libraries
if (!SXMPMeta::Initialize() || !SXMPFiles::Initialize())
{
XMP_StringPtr pszErrorMessage = "Libraries failed to load";
throw XMP_Error(kXMPErr_InternalFailure, pszErrorMessage);
}
ATLTRACE("\nXMP library initialized on thread %lu\n", GetCurrentThreadId());
}
~XMPLibraryInitializer()
{
// Terminate XMP libraries
SXMPFiles::Terminate();
SXMPMeta::Terminate();
ATLTRACE("\nXMP library terminated on thread %lu\n", GetCurrentThreadId());
}
};
HRESULT MyFunc()
{
// Statically initialize the Adobe XMP library
try
{
static XMPLibraryInitializer xmpLibraryInitializer;
}
catch (const XMP_Error & e)
{
return E_UNEXPECTED;
}
// ...
}
This seems to operate fine, except the output I see is
XMP library initialized on thread 5820
...
XMP library terminated on thread 3104
Is there any explanation for the different thread numbers? And if the numbers are different, does that mean it doesn't comply with the docs requiring single threaded initialization and termination?
A simple static singleton function should suffice, if you want to keep hold of it until the program exits.
The static initialisation is guaranteed to be only done one in an efficient thread-safe manner (from C++11) usually involving a mutex double-check of a guard flag.
You would call it every place where you can't be sure you already have the ATX set up. There is no point, but no harm, in calling it in the middle of some repeated transaction. So do call it in GiveMeAToken() but don't call it in UseToken() because you know it must have been called in order to get the token?
I updated this to show how a simple bool Initialise success status can be kept, though the actual return from SXMPMeta::Initialize() may be more complex:
struct SomeATXThing
{
bool good;
SomeATXThing()
{
good = SXMPMeta::Initialize();
}
~SomeATXThing()
{
if (good)
SXMPMeta::Terminate();
}
};
SomeATXThing* AtxEnsureSingleton()
{
static SomeATXThing someATXThing;
return someATXThing.good ? &someATXThing : nullptr;
}
Note one caveat with singletons is that they are destructed in reverse order to the end of their construction. Some other independently earlier constructed singleton MUST NOT rely on the existence of this singleton during its destruction, but it is safe for one singleton constructor to invoke another during construction and again during destruction. There is no easy enforcement of this rule, except ABEND.
You can do phoenix reactivation where the object (generally relying on undefined behaviour existence of object instance addresses after destruction), but it is a load of grief.

Delay initialisation of static variables in a 3rd party library

I'm linking against a 3rd party library that uses static variables. These end up getting initialised before main and grab resources prematurely, causing some havoc in my application. Is there any idiom / technique/ wrapping method, to regain control and define the point in execution where the library is allowed initialise all of its static variables without hacking at the library itself?
Specifically, I have a thirdpartylib::system object, that once defined in main, grabs all sorts of resources before main is entered. The compiler sees that the code can be hit, and then goes about initialising all of its static vars out of control of the library consumer. Ideally, I'd like some kind of guard to stop this until I say so, like . .
// my code that may exit before I want the lib stuff to be invoked
{
LET_SYSTEM_RUN_RIOT();
thirdpartylib::system sys;
// do some stuff with it
KILL_IT_ALL_WITH_FIRE();
}
The only thing you can do is build it dynamically and load it at runtime via dload/LoadLibrary. Then you are in complete control of when the library initializes itself. By linking statically, you are conceptually making the library part of your application, which means it will initialize as part of you application, i.e. before your main function.

Initialize before any global objects

I am writing a C++ memory profiler.
As everyone knows, an executable program may contain many global objects,
and its DLL modules may contain global objects as
well. These global objects will be initialized with CRT
initialization - after the entry point and before WinMain; for DLLs,
the entry point is _DllMainCRTStartup, before you get into DllMain,
all the global objects of the DLL are initialized.
A global object may allocate memory. so a memory profiler
must be initialized before any global object initialization. After
doing a lot of researching, I found that this is not an easy job.
One idea is using CreateProcess with CREATE_SUSPENDED flag - try
to get a first chance. After that, use CreateRemoteThread to call
LoadLibrary in the target process to load an injection DLL, and
initialize that DLL. But it doesn't work because this will load
all the implicit-linking DLLs of the executable program first. Maybe CreateRemoteThread triggers this behavior?
So, how do we get the first chance?
There might be a way to do this otherwise using very platform-specific ways, but one way to solve the issue is to combine lazy initialization with dylib loading.
For example, say your memory allocator functions are exported like this:
API void* exported_alloc();
API void exported_free(void* mem);
... inside a dylib called mem.dll.
In this case, to ensure that all of your other dylibs can get to it when they are being loaded, we can create a central statically-linked library (ex: sdk.lib) that all of your dylibs link against with a header like so:
#ifndef MEMORY_H
#define MEMORY_H
// Memory.h
void* my_alloc();
void my_free(void* mem);
#endif
... which we can implement like so:
static void* (exported_alloc)() = 0;
static void (exported_free)(void* mem) = 0;
static void initialize()
{
if (!exported_alloc)
{
// Load 'mem.dll' (ex: 'LoadLibrary') and look up
// symbols for `exported_alloc` and `exported_free`
// (ex: GetProcAddress).
}
}
void* my_alloc()
{
initialize();
return exported_alloc();
}
void my_free(void* mem)
{
initialize();
exported_free(mem);
}
.. Then call FreeLibrary at the appropriate time when you're finished with the DLL. This incurs a bit of run-time overhead (similar to the overhead of accessing a singleton), but is a cross-platform solution (provided that you have a cross-platform means of loading/unloading dylibs/shared libs at runtime).
With this solution, all of your DLLs allocating memory at a global scope would then load mem.dll prior to performing any memory allocations in a lazy-initialized kind of way, ensuring that they all have access to your memory functions at the appropriate time.

what is the best way to initialize my global data in shared library?

I have a single class which does all the required initialization.
currently i have declared a global object of this class type, which is being instantiated on library load.
I've seen other ways, like delaring
BOOL APIENTRY DllMain
entry point for the shared library, and does the actual initialization on process attach.
does this differ from letting the implicit global initialization to its job? which way is better?
This is what happens during C++ DLL startup:
System calls DLL's entry point, generated by you compiler
Entry point calls DllMainCRTStartup (name may differ), which initializes C/C++ runtimes and instantiates all global objects.
DllMainCRTStartup then calls user-defined DllMain.
I personally prefer DllMain, because this way I can explicitly control order of initialization. When you use global objects in different compilation units, they will be initialized in random order which may bring some unexpected surprises 10 minutes before the deadline.
DllMain also let's you do per-thread initialization, which you can not achieve with global objects. However, it is not portable to other platforms.
P.S. You do NOT need mutex in DllMain, as all calls to it are already serialized under process-global critical section. I.e. it is guaranteed two threads will not enter it at the same time for any purpose. This is also the reason why you should not communicate with other threads, load other libraries etc. from this function; see MSDN article for explanation.
A couple of things that should never be done from DllMain:
Call LoadLibrary or LoadLibraryEx (either directly or indirectly). This can cause a deadlock or a crash.
Synchronize with other threads. This can cause a deadlock.
Acquire a synchronization object that is owned by code that is waiting to acquire the loader lock. This can cause a deadlock.
Initialize COM threads by using CoInitializeEx. Under certain conditions, this function can call LoadLibraryEx.
Call the registry functions. These functions are implemented in Advapi32.dll. If Advapi32.dll is not initialized before your DLL, the DLL can access uninitialized memory and cause the process to crash.
Call CreateProces. Creating a process can load another DLL.
Call ExitThread. Exiting a thread during DLL detach can cause the loader lock to be acquired again, causing a deadlock or a crash.
Call CreateThread. Creating a thread can work if you do not synchronize with other threads, but it is risky.
Create a named pipe or other named object (Windows 2000 only). In Windows 2000, named objects are provided by the Terminal Services DLL. If this DLL is not initialized, call to the DLL can cause the process to crash.
Use the memory management function from the dynamic C Run-Time (CRT). If the CRT DLL is not initialized, calls to these functions can cause the process to crash.
Call functions in User32.dll or Gdi32.dll. Some functions load another DLL, which may not be initialized.
Use managed code.
You need a static boolean initialization variable and a mutex. Statically initialize "initialized" to 0. In your DllMain(), make a call to CreateMutex(). Use bInitialOwner=0 and a unique name for lpName that's unique to your application. Then use WaitForSingleObject() to wait for the mutex. Check if initialized is non-zero. If not, do your initialization, and then set initialized to 1. If initialized is non-zero, do nothing. Finally, release the mutex using ReleaseMutex() and close it using CloseHandle().
Here's some pseudo-code, with error and exception handling omitted:
initialized = 0;
DllMain()
{
mutex = CreateMutex(..., 0, "some-unique-name");
result = WaitForSingleObject(handle, ...);
if (result == WAIT_OBJECT_0) {
if (!initialized) {
// initialization goes here
initialized = 1;
}
}
ReleaseMutex(mutex);
CloseHandle(mutex);
}
hi i would recommend u to prefer a signleton class where u can only create a single object of a class and use it. Sigleton class can be created with a private constructor. Now suppose ur class A is a singleton class its object can be used in a constructor of each Class which u want to initialize. Please give us some sample code so other may help u better.

Can I replace code in main() into a constructor of a global object?

Assuming that init is the last global object being initialized before main() (and we don't need any command line argument), can I do something like:
struct int_main {
int_main ()
{
//... start code execution
}
}init;
int main ()
{
}
Asking the question in this way, because I am interested in knowing if main() assures anything other than:
argc, argv from command line
All global objects are initialized
before it
You do not have a guarantee that all global objects are constructed before your object, so you may not use any of them. That includes vital parts of iostreams.
I normally use the pattern that main() just constructs the application object and invokes a method on it to perform the actual work.
You would have a hard time catching any exception from the int_main constructor.
Also you would have a hard time returning a process exit code with complete unwinding of the stack.
That's mainly what main provides in C++: a place to catch exceptions, and a means to return normally (not just exit) with a specified process exit code.
Cheers & hth.,
Within C\C++ you can declare the entry point of your application via the visual studio IDE. It's the convention that the entry point into you're code will be either be Main or in the case of a win32 exe WinMain.
As to answer your question, the CRT will iniailize all global variables in the order of
C Primitive Types
C Struct Types and or C++ Class types
Call the class constructors
Call the Entry point into your application, this will be done from CRTStartup (correct me if i'm wrong)
In theory this is possible, but you're not assured of the initialization order of global objects, so you are not going to have an assurance of which object will be initialized last, and therefore you're going to have a problem with running a "main" inside a global object that may not have the proper state of the program setup before its constructor is called. Furthermore, you're not going to be capable of suspending the execution of your "main" object's constructor to wait for the proper starting state to exist if such a scenario occurs.
Additionally, since the OS's runtime will be calling your actual main() function in order to actually "run" your program regardless of the presence of a "main" global object or not, you're going to need to return a value from 'main()` in order for the OS runtime to determine the exit status of your program.