Closed dmascle closed 5 years ago
Hi,
Thank you, I'm glad you find it helpful.
Admittedly, it's not very elegant, but you should be able to achieve this by invoking System.exit(int)
in your task. For example like this:
jvmPool.submit((Callable<Long> & Serializable) () -> {
SomeCppFunctionCall(); // A CRASH HAPPENS HERE
if (HasCppCallCrashed()) {
System.exit(1);
}
return rand.nextLong();
});
I hope that helps.
Thank you for your answer !
I'm sorry I forgot to mention that I already tried that solution and there is a problem with it. Actually, the process terminates as excepted after System.exit() call, however it seems the submitted task isn't considered as finished, thus the process pool restarts a new process and re-run the task from the beginning... which is not what I would want in such case.
Would it be possible to "tell" the process pool that the task is finished before calling System.exit() ?
Thank you !
Ah, okay, that makes the situation a bit more complicated.
Unfortunately, the API doesn't allow for doing this at the moment. I definitely think it should, though, as it's a completely valid use case. The solution could be as simple as making the exit
static method of JavaProcess
public.
At any rate, if you need an immediate workaround, this should do the trick:
jvmPool.submit((Callable<Long> & Serializable) () -> {
SomeCppFunctionCall(); // A CRASH HAPPENS HERE
if (HasCppCallCrashed()) {
try {
Method exitMethod = JavaProcess.class.getDeclaredMethod("exit");
exitMethod.setAccessible(true);
exitMethod.invoke(null);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
return rand.nextLong();
});
Hi,
I have released a new version, 3.0.2, that allows you to terminate the Java process from within a task in an orderly fashion like this:
jvmPool.submit((Callable<Long> & Serializable) () -> {
SomeCppFunctionCall(); // A CRASH HAPPENS HERE
if (HasCppCallCrashed()) {
JavaProcess.exit();
}
return rand.nextLong();
});
This ensures that the process terminates after finishing the task. Also, the submission will be considered successfully executed so it won't be delegated to other processes.
Let me know if that solves your problem.
Cheers, Viktor
Hi,
I tried with the new version and calling JavaProcess.exit() and it works great ! Thank you for your quick answers !
I just modified a little bit the code to throw an exception after JavaProcess.exit() call, because if I don't do so, the caller that submitted the task doesn't detect there was an issue in the task. Actually, my code is more like:
Future<Long> ret =jvmPool.submit((Callable<Long> & Serializable) () -> {
try {
return SomeCppFunctionCall();
} catch(Exception e) {
JavaProcess.exit();
throw e;
}
});
try {
return ret.get();
} catch (ExecutionException e) {
HandleCommandException(e);
}
That way, I can catch the ExecutionException at caller side. Do you think it is the right way to do it ?
thank you again !
Hi,
Yeah, that all looks good to me. Any exception thrown from the task will be wrapped in an ExecutionException
and rethrown in Future.get()
, so your approach is guaranteed to work. 👍
Kind regards, Viktor
Hi,
Firstly, congratulation for this great library, it is very helpful. I just had a question about it (not an issue) !
I use this library to call some C++ code and I was wondering if it could be possible to terminate a process in which a crash happened while running a task, so that it won't be used anymore for new tasks. The goal is to stop using process in which unmanaged C++ memory may be corrupted even if the crash exception was catched correctly.
For ex: jvmPool.submit((Callable & Serializable) () -> {
SomeCppFunctionCall(); // A CRASH HAPPENS HERE
return rand.nextLong();
}));
Is there a way to "tell" the ProcessPool to terminate the current process in which the crash happened ?
Thank you !