JNI and thread unsafe initialization - java-native-interface

Suppose I am writing a JNI binding to a C library, which requires an initialization function to be called that isn't thread-safe. Given that the JVM doesn't serialize calls to JNI_OnLoad, how can I avoid racing against someone else's library that also binds to my library?

Related

Are static free functions thread safe?

I am writing a multithreaded program and have a function that will be called from multiple threads that is a static free function within a cpp file. This function will never be called from outside of the cpp file so I wanted to make it static so that it had internal linkage.
Googling around I found a lot of people saying "static functions are not thread safe" but then when I go to read up about it everyone seems to be talking about static member functions, not static free functions.
Are static free functions thread safe (assuming they don't access any shared state between threads)?
Any function that accesses no shared state is inherently thread safe. You only get a data race when you have unprotected read/writes to shared state. If there is no shared state, you can't have a data race.
This is why purely functional languages are naturally thread safe. If a function doesn't have side effects, then you can call it in as many threads as you want.
Static functions are the same as other functions. It is not the function, it is what the function does.
I think some people are mixing between terms. static function vs function with static variables.
while static function may be safe or not, a function with static variables is not safe without synchronization.
An example of such a function is strtok which keeps in a static variable the continuation point. when several threads use the old strtok, it may cause a mixture between the inputs.

Extending lifetime of Boost log core

I want to extend lifetime of the boost::log::core for termination process.
I know that this is not recommended in the documentation. But I tried to use Schwarz counter for core to keep it until last destructor of global variable used it.
Core uses the shared pointer with Meyer's singleton. is it possible to implement Schwarz counter or nifty initialization core ?
The core::get() method returns a shared_ptr to the core, which is what implements the Schwarz counter. You can call this method during the normal operation of the program (i.e. while main() is executing) and save that pointer in your data structures that are guaranteed to be present during termination. While the shared_ptr exists, you can access the core through that pointer (but not necessarily through core::get()).
Note that all loggers provided by the library also save the pointer to the core internally. For example, if you're performing termination in an object destructor, make a logger a member of that object and you will be able to emit simple log records during the destruction.
Note that the core is not the only singleton the library maintains, and other singletons are not protected from destruction by this method. For example, you cannot use global loggers during program termination.

Which standard c++ functions and types support reentrancy?

The C++ Standard (c++14 and also the current working draft) states that
Except where explicitly specified in this document, it is
implementation-defined which functions in the C++ standard library may
be recursively reentered.
Except of std::recursive_mutex I couldn't find any type or function in the standard where it is explicitly specified that it can be recursively reentered safely. Even for std::recursive_mutex the standard states that:
It is unspecified how many levels of ownership may be acquired by a
single thread.
My questions for C++17:
Which types or functions, defined by the C++ standard, have to be implemented in a way that they can be recursively reentered?
Reentrant code may not call non-reentrant functions (see rules for reentrancy below). With this in mind, is it correct to summarize that C ++ code can only be safely reentrant if no C++ standard types or functions are used?
Please note, that reentrancy and thread-safety are orthogonal concepts:
In computing, a computer program or subroutine is called reentrant if
multiple invocations can safely run concurrently on a single processor
system, where a reentrant procedure can be interrupted in the middle
of its execution and then safely be called again ("re-entered") before
its previous invocations complete execution. The interruption could be
caused by an internal action such as a jump or call, or by an external
action such as an interrupt or signal, unlike recursion, where new
invocations can only be caused by internal call.
This definition of reentrancy differs from that of thread-safety in
multi-threaded environments. (...) Conversely, thread-safe code does
not necessarily have to be reentrant (...)
Rules for reentrancy:
Reentrant code may not hold any static or global non-constant data.
Reentrant code may not modify itself.
Reentrant code may not call non-reentrant computer programs or routines.
Which types or functions, defined by the C++ standard, have to be implemented in a way that they can be recursively reentered?
Reentrancy is a pre-requisite for asynchronous signal safety. Therefore functions which are specified as signal-safe must be implemented as reentrant.
[support.signal]
An evaluation is signal-safe unless it includes one of the following:
a call to any standard library function, except for plain lock-free atomic operations and functions explicitly identified as signal-safe;
A plain lock-free atomic operation is an invocation of a function f from [atomics], such that:
f is the function atomic_­is_­lock_­free(), or
f is the member function is_­lock_­free(), or
f is a non-static member function invoked on an object A, such that A.is_­lock_­free() yields true, or
f is a non-member function, and for every pointer-to-atomic argument A passed to f, atomic_­is_­lock_­free(A) yields true.
As such, those plain lock-free atomic opreations must be reentrant.

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.

Calling C like callback within a thread

I have a C static library with,
A callback definition:
typedef void (*HandleEvents) (enum events eventID, int msgSize, char *msg);
A function in the library:
int init(HandleEvents _handleEvents)
And another C++ GUI developed in VS. which links this static lib and calls init function of the lib giving a function pointer.
init(&CGateway::handleEventsFunc);
where CGateway::handleEventsFunc is a static class function.
In a thread in the static lib calls this callback of the C++ GUI. But I got errors of heap corruption.
In sum, there are 2 threads, one in static library and one in Main GUI app. Static library calls Main GUI's class function.
So what is the correct way of calling callback function in a thread?
[incorrect statement about multiple heaps, as pointed out by Adisak, deleted]
One thing to check is, that you are not doing anything GUI related from the worker thread. Accessing windows is only safe from the main thread where they were created. If you have to update GUI stuff, you have to decouple that by using PostMessage().
Make sure to use a mutex or other form of thread protection for any variables that can be modified by one thread and are used (read or modified) by another thread.
In multithreaded code, heap corruption is quite often a symptom of code that is not thread-safe accessing memory.