Skip to content

Commit 6559dc8

Browse files
authored
Merge pull request #68 from notgull/abort-guards
Add panic guards to extern "C" functions
2 parents 9229bb2 + d6ccefa commit 6559dc8

3 files changed

Lines changed: 271 additions & 212 deletions

File tree

android-activity/src/game_activity/mod.rs

Lines changed: 47 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use std::fs::File;
55
use std::io::{BufRead, BufReader};
66
use std::marker::PhantomData;
77
use std::ops::Deref;
8-
use std::os::raw;
98
use std::os::unix::prelude::*;
109
use std::ptr::NonNull;
1110
use std::sync::{Arc, RwLock};
@@ -24,6 +23,7 @@ use ndk::asset::AssetManager;
2423
use ndk::configuration::Configuration;
2524
use ndk::native_window::NativeWindow;
2625

26+
use crate::util::{abort_on_panic, android_log};
2727
use crate::{
2828
util, AndroidApp, ConfigurationRef, InputStatus, MainEvent, PollEvent, Rect, WindowManagerFlags,
2929
};
@@ -595,19 +595,6 @@ pub unsafe extern "C" fn GameActivity_onCreate(
595595
GameActivity_onCreate_C(activity, saved_state, saved_state_size);
596596
}
597597

598-
fn android_log(level: Level, tag: &CStr, msg: &CStr) {
599-
let prio = match level {
600-
Level::Error => ndk_sys::android_LogPriority::ANDROID_LOG_ERROR,
601-
Level::Warn => ndk_sys::android_LogPriority::ANDROID_LOG_WARN,
602-
Level::Info => ndk_sys::android_LogPriority::ANDROID_LOG_INFO,
603-
Level::Debug => ndk_sys::android_LogPriority::ANDROID_LOG_DEBUG,
604-
Level::Trace => ndk_sys::android_LogPriority::ANDROID_LOG_VERBOSE,
605-
};
606-
unsafe {
607-
ndk_sys::__android_log_write(prio.0 as raw::c_int, tag.as_ptr(), msg.as_ptr());
608-
}
609-
}
610-
611598
extern "Rust" {
612599
pub fn android_main(app: AndroidApp);
613600
}
@@ -617,55 +604,57 @@ extern "Rust" {
617604
// by android_native_app_glue.
618605
#[no_mangle]
619606
pub unsafe extern "C" fn _rust_glue_entry(app: *mut ffi::android_app) {
620-
// Maybe make this stdout/stderr redirection an optional / opt-in feature?...
621-
let mut logpipe: [RawFd; 2] = Default::default();
622-
libc::pipe(logpipe.as_mut_ptr());
623-
libc::dup2(logpipe[1], libc::STDOUT_FILENO);
624-
libc::dup2(logpipe[1], libc::STDERR_FILENO);
625-
thread::spawn(move || {
626-
let tag = CStr::from_bytes_with_nul(b"RustStdoutStderr\0").unwrap();
627-
let file = File::from_raw_fd(logpipe[0]);
628-
let mut reader = BufReader::new(file);
629-
let mut buffer = String::new();
630-
loop {
631-
buffer.clear();
632-
if let Ok(len) = reader.read_line(&mut buffer) {
633-
if len == 0 {
634-
break;
635-
} else if let Ok(msg) = CString::new(buffer.clone()) {
636-
android_log(Level::Info, tag, &msg);
607+
abort_on_panic(|| {
608+
// Maybe make this stdout/stderr redirection an optional / opt-in feature?...
609+
let mut logpipe: [RawFd; 2] = Default::default();
610+
libc::pipe(logpipe.as_mut_ptr());
611+
libc::dup2(logpipe[1], libc::STDOUT_FILENO);
612+
libc::dup2(logpipe[1], libc::STDERR_FILENO);
613+
thread::spawn(move || {
614+
let tag = CStr::from_bytes_with_nul(b"RustStdoutStderr\0").unwrap();
615+
let file = File::from_raw_fd(logpipe[0]);
616+
let mut reader = BufReader::new(file);
617+
let mut buffer = String::new();
618+
loop {
619+
buffer.clear();
620+
if let Ok(len) = reader.read_line(&mut buffer) {
621+
if len == 0 {
622+
break;
623+
} else if let Ok(msg) = CString::new(buffer.clone()) {
624+
android_log(Level::Info, tag, &msg);
625+
}
637626
}
638627
}
639-
}
640-
});
628+
});
641629

642-
let jvm: *mut JavaVM = (*(*app).activity).vm;
643-
let activity: jobject = (*(*app).activity).javaGameActivity;
644-
ndk_context::initialize_android_context(jvm.cast(), activity.cast());
630+
let jvm: *mut JavaVM = (*(*app).activity).vm;
631+
let activity: jobject = (*(*app).activity).javaGameActivity;
632+
ndk_context::initialize_android_context(jvm.cast(), activity.cast());
645633

646-
let app = AndroidApp::from_ptr(NonNull::new(app).unwrap());
634+
let app = AndroidApp::from_ptr(NonNull::new(app).unwrap());
647635

648-
// Since this is a newly spawned thread then the JVM hasn't been attached
649-
// to the thread yet. Attach before calling the applications main function
650-
// so they can safely make JNI calls
651-
let mut jenv_out: *mut core::ffi::c_void = std::ptr::null_mut();
652-
if let Some(attach_current_thread) = (*(*jvm)).AttachCurrentThread {
653-
attach_current_thread(jvm, &mut jenv_out, std::ptr::null_mut());
654-
}
636+
// Since this is a newly spawned thread then the JVM hasn't been attached
637+
// to the thread yet. Attach before calling the applications main function
638+
// so they can safely make JNI calls
639+
let mut jenv_out: *mut core::ffi::c_void = std::ptr::null_mut();
640+
if let Some(attach_current_thread) = (*(*jvm)).AttachCurrentThread {
641+
attach_current_thread(jvm, &mut jenv_out, std::ptr::null_mut());
642+
}
655643

656-
// XXX: If we were in control of the Java Activity subclass then
657-
// we could potentially run the android_main function via a Java native method
658-
// springboard (e.g. call an Activity subclass method that calls a jni native
659-
// method that then just calls android_main()) that would make sure there was
660-
// a Java frame at the base of our call stack which would then be recognised
661-
// when calling FindClass to lookup a suitable classLoader, instead of
662-
// defaulting to the system loader. Without this then it's difficult for native
663-
// code to look up non-standard Java classes.
664-
android_main(app);
665-
666-
if let Some(detach_current_thread) = (*(*jvm)).DetachCurrentThread {
667-
detach_current_thread(jvm);
668-
}
644+
// XXX: If we were in control of the Java Activity subclass then
645+
// we could potentially run the android_main function via a Java native method
646+
// springboard (e.g. call an Activity subclass method that calls a jni native
647+
// method that then just calls android_main()) that would make sure there was
648+
// a Java frame at the base of our call stack which would then be recognised
649+
// when calling FindClass to lookup a suitable classLoader, instead of
650+
// defaulting to the system loader. Without this then it's difficult for native
651+
// code to look up non-standard Java classes.
652+
android_main(app);
653+
654+
if let Some(detach_current_thread) = (*(*jvm)).DetachCurrentThread {
655+
detach_current_thread(jvm);
656+
}
669657

670-
ndk_context::release_android_context();
658+
ndk_context::release_android_context();
659+
})
671660
}

0 commit comments

Comments
 (0)