2
votes

I'm a Java programmer writing a JNI application which calls native C code. What I want is to detect native program crash from Java code that calls the native code.

I know that there is no exception handling in C but just curious whether I can write dangerous codes "safely" inside try-catch block in Java (e.g.code that may contain bad pointer in runtime or file not found cases). In that case the code will crash, but I was looking for a safe way to report it.

3
You can handle segmentation faults( SIGSEGV signals) , but your program is in a bad place, once you get one anyway. - this
Who says that you can handle exceptions in C? You just have to build it yourself instead of relying on pre-defined code. - ciphermagi
@JonahNelson Why would you have to write your own code? Have you ever heard of libraries. - this
@self. Yes The program may be in the bad place, I just want to report it safely. - Shafiul

3 Answers

4
votes

I believe you're taking the wrong approach. As a language C is not a place where "it's better to ask for forgiveness than permission." You must ask for permission in C, though in the event of a disaster, you can certainly do some cleanup:

You should look into signal handling.

When you do something like

int *a = NULL;
int b = *a;    //segfault

Your program will receive SIGSEGV, which will force your program to quit, unless you have installed a signal handler.

Most unhandled signals will cause program termination, and most can be caught (SIGKILL for example cannot be caught).

This allows you to do some cleanup.

#include <signal.h>
#include <stdio.h>

//typedef void (*sighandler_t)(int);

void myhandler(int signal){
    printf("oh noes...\n");
}
int main(void)
{
    signal(SIGSEGV, myhandler);
    int *a = NULL;
    int b = *a;    //segfault
    return 0;
}

None of this is recommended though. You MUST know the contents of your pointers at all times. Otherwise, giants will raze your village.

EDIT: the signal() function is suggested as deprecated. New code should use [sigaction()][2] instead. This example uses signal() for its simplicity.

2
votes

No you can't reasonably detect a native crash from Java. If such a crash happens, your program is likely to be killed before you have a chance to catch it.

What you can do is to check for return codes. Any decently written C library will return you an error code if it fails (note that's different from crash). You can use those codes and translate them in Java exceptions if you wish to.

For crashes, you could use the "signal" APIs, though it's not as straight forward as it looks: if you actually caught a crash, then there's not much you could be doing as the entire program memory may have been corrupted. I'd recommend against it if you are a beginner.

2
votes

C doesn't really have exceptions. It has two things which play a similar role, but which are vastly different from one another: signals and error codes.

Let's consider error codes first. When a function call in C fails, it will typically signal this failure to the caller by returning an error code, or by returning a placeholder value (e.g, 0, -1, or NULL) and setting an error in errno, or storing it in a location that can be retrieved by calling another method. No special effort is required to handle these exceptions. Simply check the return values of functions, e.g.

FILE *fh = fopen("example", "r");
if (fh == NULL) {
    fprintf(stderr, "Couldn't open file: %s\n", strerror(errno));
    return -1;
}
// do things with fh...

Signals, on the other hand, are used in C to denote really unusual situations, such as an attempt to execute invalid code or dereference a bad pointer, or other external conditions like the user pressing control-C to terminate your program. You can attempt to handle some such signals using the signal() function, but the ones you've described, like a bad pointer, typically indicate that the process is screwed up in a rather permanent way, so allowing them to terminate the process is usually the correct solution.

If you are indeed running code that is prone to triggering segmentation faults, it would be wise to run it in a separate process, rather than allowing it to potentially corrupt the state of a Java runtime.