Reattempting unsuccessful call to JNI_CreateJavaVM - c++

The idea is to try calling JNI_CreateJavaVM with a large heap memory parameter, and, if that fails, call it again with the heap memory parameter omitted so a default is used instead.
A failure on the first call gives me a return code of JNI_ENOMEM (not enough memory), which is what I have anticpiated.
However, it seems that a subsequent call to JNI_CreateJavaVM fails with a return code of -1 (JNI_ERR: unknown error).
Is there some kind of reset I have to perform before I retry? Needless to say, my subsequent call on its own is successful.
I'm tagging this C and C++ as the methods of accessing the interfaces are identical in these languages.

Related

Rare segmentation fault during object creation with new

In a Java application, I use JNI to call several C++ methods. One of the methods creates an object that has to persist after the method finished and that is used in other method calls. To this end, I create a pointer of the object, which I return to Java as a reference for later access (note: the Java class implements Closable and in the close method, I call a method to delete the object).
However, in rare cases, approximately after 50.000 calls, the C++ code throws a segmentation fault. Based on the content of the log file, only a few lines of code are suspicious to be the source of error (they between the last printed log message and the next one):
MyObject* handle = new MyObject(some_vector, shared_ptr1, shared_ptr2);
handles.insert(handle); // handles is a std::set
jlong handleId = (jlong) handle;
I'd like to know whether there is a possible issue here apart from the fact that I'm using old-style C pointers. Could multi-threading be a problem? Or could the pointer ID be truncated when converted to jlong?
I also want to note that from my previous experience, I'm aware that the log is only a rough indicator of where a segmentation fault occurred. It may as well have been occurred later in the code and the next log message was simply not printed yet. However, reproducing this error may take 1-2 days, so I'd like to check out whether these lines have a problem.
After removing my std::set from the code, the error did not occur anymore. Conclusion: std::set in multithreading must be protected to avoid unrecoverable crashes.

What may cause EnumProcesses() to fail?

The documentation states:
If the function fails, the return value is zero. To get extended error
information, call GetLastError.
But it doesn't give any example how the function could possibly fail.
For unit testing I need to reliably create a situation that makes EnumProcesses() fail.
Like most functions, it can fail if you pass it invalid parameters. In this case that means a smaller PID array than the size you tell it or a NULL pointer for the received count. It is a bit risky to do this on purpose because you don't know if the function uses SEH to protect against this or if it will just crash.
Internally the function has to allocate some memory before calling into NTDLL to get the process information and this can cause the function to fail if there is not enough memory available.
You should call EnumProcesses in a helper function to abstract away the memory/retry details anyway and that would be a good place to simulate failures when needed.
If you absolutely need the function itself to fail you could hook it with something like Microsoft Detours or IAT hooking...

Once cudaMalloc returns out of memory, every cuda API call returns failure

With the CUDA, is it possible to use like a garbage-collection?
For example, when I got an out-of-memory error from cudaMalloc(...), can I free the previously allocated data and retry allocating memory?
Once cudaMalloc(...) returns out-of-memory,
the following cuda calls seem to return the out-of-memory after then.
Even when I call cudaFree with the valid device pointer allocated previously, cudaFree returns out-of-memory...
cudaDeviceReset() is not a good way to recover the state for my case.
Once CUDA encounters an error, all API calls will return that error. If the error corrupts the CUDA context, there's not much to do except reset the device (cudaDeviceReset). If the CUDA context has not been corrupted then the state can be reset to cudaSuccess by calling cudaGetLastError().
As per Robert Crovella's comment, a failed cudaMalloc probably does not corrupt the CUDA context and therefore you should be able to recover. This is not necessarily true of other causes of an error, and each case may be different.

Exit the entire recursion stack

I'm calling a function fooA from main() that calls another function fooB that is recursive.
When I wish to return, I keep using exit(1) to halt execution. What is the right way to exit when the recursion tree is deep?
Returning through the recursion stack may not be of help because returning usually clears a part solution I build and I don't want to do that. I want to do execute more piece of code from main().
I read Exceptions can be used, it would be nice if I can get a code snippet.
The goto statement won't work to hop from one function back to another; Nikos C. is correct that it wouldn't account for releasing the stack frames of each of the calls you've made, so when you got to the function you goto'ed to, the stack pointer would be pointing to the stack frame of the function you were just in... no, that just won't work. Similarly, you can't simply call (either directly, or indirectly via a function pointer) the function you want to end up in when your algorithm is done. You'd never get back to the context you were in prior to diving into your recursive algorithm. You could conceivably architect a system this way, but in essence each time you did this you'd "leak" what was currently on the stack (not quite the same as leaking heap memory, but a similar effect). And if you were deep into a highly recursive algorithm, that could be a lot of "leaked" stack space.
No, you need to somehow return back to the calling context. There are only three ways to do so in C++:
Exit each function in turn by returning from it to its caller
backing up through the call chain in an orderly fashion.
Throw an exception and catch it at the point right after you
launched into your recursive algorithm (which automatically destroys
any objects created by each function on the stack in an orderly
fashion).
Use setjmp() & longjmp() to do something similar to throwing &
catching an exception, but "throwing" a longjmp() will not destroy
objects on the stack; if any such objects own heap allocations,
those allocations will be leaked.
To do option 1, you have to write your recursive function such that once a solution is reached, it returns some sort of indication that it's complete to its caller (which may be the same function), and its caller sees that fact & relays that fact on to its caller by returning to it (which may be the same function), so on and so on, until finally all stack frames of the recursive algorithm are released and you return to whatever function called the first function in the recursive algorithm.
To do option 2, you wrap the call to your recursive algorithm in a try{...} and immediately after it you catch(){...} the expected thrown object (which could conceivably be the result of the computation, or just some object that lets the caller know "hey, I'm done, you know where to find the result"). Example:
try
{
callMyRecursiveFunction(someArg);
}
catch( whateverTypeYouWantToThrow& result )
{
...do whatever you want to do with the result,
including copy it to somewhere else...
}
...and in your recursive function, when you finish the results, you simply:
throw(whateverTypeYouWantToThrow(anyArgsItsConstructorNeeds));
To do option 3...
#include <setjmp.h>
static jmp_buf jmp; // could be allocated other ways; the longjmp() user just needs to have access to it.
.
.
.
if (!setjmp(jmp)) // setjmp() returns zero 1st time, or whatever int value you send back to it with longjmp()
{
callMyRecursiveFunction(someArg);
}
...and in your recursive function, when you finish the results, you simply:
longjmp(jmp, 1); // this passes 1 back to the setjmp(). If your result is an int, you
// could pass that back to setjmp(), but you can't pass zero back.
The bad thing about using setjmp()/longjmp() is that if there are any stack-allocated objects still "alive" on the stack when you call longjmp(), execution will jump back to the setjmp() point, skipping the destructors for those objects. If your algorithm uses only POD types, that's not an issue. It's also not an issue if the non-POD types your algorithm uses do NOT contain any heap allocations (e.g. from malloc() or new). If your algorithm uses non-POD types that contain heap allocations, then you're only safe with options 1 & 2 above. But if your algorithm meets the criteria of being OK with setjmp()/longjmp(), and if your algorithm is buried under a ton of recursive calls at the point it finishes, setjmp()/longjmp() may be the fastest way back to the initial calling context. If that won't work, option 1 is probably your best bet in terms of speed. Option 2 may seem convenient (and would possibly eliminate a condition check at the start of each recursion call), but the overhead associated with the system automatically unwinding the callstack is somewhat significant.
It's typically said you should reserve exceptions for "exceptional events" (events expected to be very rare), and the overhead associated with unwinding the callstack is why. Older compilers used something akin to setjmp()/longjmp() to implement exceptions (setjmp() at the location of the try & catch, and longjmp() at the location of a throw), but there was of course extra overhead associated with determining what objects on the stack need destroyed, even if there are no such objects. Plus, every time you'd run across a try, it would have to save the context just in case there was a throw, and if exceptions are truly exceptional events, the time spent saving that context was simply wasted. Newer compilers are now more likely to use what are known as "Zero Cost Exceptions" (a.k.a. Table Based Exceptions), which seems like that would solve all the world's problems, but it doesn't.... It makes normal runtime faster because there is no longer a need to save the context every time you run across a try, but in the event that a throw executes, there is now even more overhead associated with decoding information stored in massive tables that the runtime has to process in order to figure out how to unwind the stack based on the location where the throw was encountered and content of the runtime stack. So exceptions aren't free, even though they're very convenient. You'll find a lot of stuff on the internet where people make claims about how unreasonably expensive they are and how much they slow down your code, and you'll also find lots of stuff by people refuting those claims, with both sides presenting hard data to bolster their claims. What you should take away from the arguments is that using exceptions is great if you expect them to rarely occur, because they result in cleaner interfaces & logic that's free of a ton of condition checking for "badness" every time you make a function call. But you shouldn't use exceptions as a means of normal communication between a caller and its callees, because that mode of communication is significantly more expensive than simply using return values.
This happened to me while finding the path from root to node of a binary tree. I was using a stack to store the nodes in preorder and the recursion wouldnt stop until the last node returned NULL. I used a global variable, integer i=1, and when I reached the node I was looking for I set that variable to 0 and used while(i==0) return stack; to allow the program to go back up the memory stack without popping my nodes off.

How can PyImport_AppendInittab fail?

According to the official docs, PyImport_AppendInittab will return -1 on failure. It does not, however, specify why this function would fail.
I'd like to know if it can only fail due to the programmer's fault (incorrect arguments, not being called at the right time, etc), or if it can also fail because of some other factors that are out of the programmer's control (like Python not being installed).
I'm asking because I want to know if I should handle this with an assert or an exception. Also, in case I should handle it with exceptions, is there any way for me to catch an error message from the Python API that specifies why the function call failed?
According to the docs, PyImport_AppendInittab() is a convenience wrapper around PyImport_ExtendInittab() and returns -1 "if the table could not be extended". Furthermore, PyImport_ExtendInittab() returns -1 "if insufficient memory could be allocated to extend the internal table". Both functions "should be called before Py_Initialize()".
Consequently, these functions should only fail if the program is out of memory. I guess they could also fail when supplied with invalid arguments, for example when trying to register a built-in module with the same name as an existing one. The latter case is easily avoided, since names of built-in modules are well known.
In summary, you can assume that a return value of -1 means "out of memory", and this should never happen since the function is only called early in the process (before Py_Initialize()), plus the amount of memory required for the module table is rather small.
If PyImport_AppendInittab() fails, Python does not provide an error string. To throw a meaningful exception, you could just report the information you know at this point: failed to add the module MODULENAME to the interpreter's builtin-in modules.