blob: 0a8707026023fc44bf0e999e29d2ff4643c9eb9d [file] [log] [blame]
// Copyright 2022 The Blaze Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::{any::Any, error::Error, fmt::Debug, panic::AssertUnwindSafe};
use blaze_jni_bridge::*;
use jni::objects::{JObject, JThrowable};
mod alloc;
mod exec;
mod logging;
mod metrics;
mod rt;
fn handle_unwinded(err: Box<dyn Any + Send>) {
// default handling:
// * caused by Interrupted/TaskKilled: do nothing but just print a message.
// * other reasons: wrap it into a RuntimeException and throw.
// * if another error happens during handling, kill the whole JVM instance.
let recover = || {
if !is_task_running() {
// only handle running task
return Ok(());
}
let panic_message = panic_message::panic_message(&err);
// throw jvm runtime exception
if jni_exception_check!()? {
let throwable = jni_exception_occurred!()?;
jni_exception_clear!()?;
throw_runtime_exception(panic_message, throwable.as_obj())?;
} else {
throw_runtime_exception(panic_message, JObject::null())?;
};
Ok(())
};
recover().unwrap_or_else(|err: Box<dyn Error>| {
jni_fatal_error!("Error recovering from panic, cannot resume: {err:?}");
});
}
fn handle_unwinded_scope<T: Default, E: Debug>(scope: impl FnOnce() -> Result<T, E>) -> T {
match std::panic::catch_unwind(AssertUnwindSafe(|| scope().unwrap())) {
Ok(v) => v,
Err(err) => {
handle_unwinded(err);
T::default()
}
}
}
fn throw_runtime_exception(msg: &str, cause: JObject) -> datafusion::error::Result<()> {
let msg = jni_new_string!(msg)?;
let e = jni_new_object!(JavaRuntimeException(msg.as_obj(), cause))?;
if let Err(err) = jni_throw!(JThrowable::from(e.as_obj())) {
jni_fatal_error!("Error throwing RuntimeException, cannot result: {err:?}");
}
Ok(())
}