Skip to content

Commit bfd8bfd

Browse files
authored
Merge pull request #133 from rust-mobile/marijn/bail-log-thread-on-read_line-error
Stop log-forwarding thread on IO errors
2 parents 98aef99 + af34189 commit bfd8bfd

File tree

3 files changed

+55
-73
lines changed

3 files changed

+55
-73
lines changed

android-activity/src/game_activity/mod.rs

Lines changed: 8 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
#![cfg(feature = "game-activity")]
22

33
use std::collections::HashMap;
4-
use std::ffi::{CStr, CString};
5-
use std::fs::File;
6-
use std::io::{BufRead, BufReader};
74
use std::marker::PhantomData;
85
use std::ops::Deref;
9-
use std::os::unix::prelude::*;
106
use std::panic::catch_unwind;
7+
use std::ptr;
118
use std::ptr::NonNull;
129
use std::sync::Weak;
1310
use std::sync::{Arc, Mutex, RwLock};
1411
use std::time::Duration;
15-
use std::{ptr, thread};
1612

1713
use libc::c_void;
18-
use log::{error, trace, Level};
14+
use log::{error, trace};
1915

2016
use jni_sys::*;
2117

@@ -29,9 +25,9 @@ use ndk::native_window::NativeWindow;
2925
use crate::error::InternalResult;
3026
use crate::input::{Axis, KeyCharacterMap, KeyCharacterMapBinding};
3127
use crate::jni_utils::{self, CloneJavaVM};
32-
use crate::util::{abort_on_panic, android_log, log_panic};
28+
use crate::util::{abort_on_panic, forward_stdio_to_logcat, log_panic, try_get_path_from_ptr};
3329
use crate::{
34-
util, AndroidApp, ConfigurationRef, InputStatus, MainEvent, PollEvent, Rect, WindowManagerFlags,
30+
AndroidApp, ConfigurationRef, InputStatus, MainEvent, PollEvent, Rect, WindowManagerFlags,
3531
};
3632

3733
mod ffi;
@@ -617,21 +613,21 @@ impl AndroidAppInner {
617613
pub fn internal_data_path(&self) -> Option<std::path::PathBuf> {
618614
unsafe {
619615
let app_ptr = self.native_app.as_ptr();
620-
util::try_get_path_from_ptr((*(*app_ptr).activity).internalDataPath)
616+
try_get_path_from_ptr((*(*app_ptr).activity).internalDataPath)
621617
}
622618
}
623619

624620
pub fn external_data_path(&self) -> Option<std::path::PathBuf> {
625621
unsafe {
626622
let app_ptr = self.native_app.as_ptr();
627-
util::try_get_path_from_ptr((*(*app_ptr).activity).externalDataPath)
623+
try_get_path_from_ptr((*(*app_ptr).activity).externalDataPath)
628624
}
629625
}
630626

631627
pub fn obb_path(&self) -> Option<std::path::PathBuf> {
632628
unsafe {
633629
let app_ptr = self.native_app.as_ptr();
634-
util::try_get_path_from_ptr((*(*app_ptr).activity).obbPath)
630+
try_get_path_from_ptr((*(*app_ptr).activity).obbPath)
635631
}
636632
}
637633
}
@@ -913,33 +909,7 @@ extern "Rust" {
913909
#[no_mangle]
914910
pub unsafe extern "C" fn _rust_glue_entry(native_app: *mut ffi::android_app) {
915911
abort_on_panic(|| {
916-
// Maybe make this stdout/stderr redirection an optional / opt-in feature?...
917-
918-
let file = {
919-
let mut logpipe: [RawFd; 2] = Default::default();
920-
libc::pipe2(logpipe.as_mut_ptr(), libc::O_CLOEXEC);
921-
libc::dup2(logpipe[1], libc::STDOUT_FILENO);
922-
libc::dup2(logpipe[1], libc::STDERR_FILENO);
923-
libc::close(logpipe[1]);
924-
925-
File::from_raw_fd(logpipe[0])
926-
};
927-
928-
thread::spawn(move || {
929-
let tag = CStr::from_bytes_with_nul(b"RustStdoutStderr\0").unwrap();
930-
let mut reader = BufReader::new(file);
931-
let mut buffer = String::new();
932-
loop {
933-
buffer.clear();
934-
if let Ok(len) = reader.read_line(&mut buffer) {
935-
if len == 0 {
936-
break;
937-
} else if let Ok(msg) = CString::new(buffer.clone()) {
938-
android_log(Level::Info, tag, &msg);
939-
}
940-
}
941-
}
942-
});
912+
let _join_log_forwarder = forward_stdio_to_logcat();
943913

944914
let jvm = unsafe {
945915
let jvm = (*(*native_app).activity).vm;

android-activity/src/native_activity/glue.rs

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,17 @@
33
//! synchronization between the two threads.
44
55
use std::{
6-
ffi::{CStr, CString},
7-
fs::File,
8-
io::{BufRead, BufReader},
96
ops::Deref,
10-
os::unix::prelude::{FromRawFd, RawFd},
117
panic::catch_unwind,
128
ptr::{self, NonNull},
139
sync::{Arc, Condvar, Mutex, Weak},
1410
};
1511

16-
use log::Level;
1712
use ndk::{configuration::Configuration, input_queue::InputQueue, native_window::NativeWindow};
1813

1914
use crate::{
2015
jni_utils::CloneJavaVM,
21-
util::android_log,
22-
util::{abort_on_panic, log_panic},
16+
util::{abort_on_panic, forward_stdio_to_logcat, log_panic},
2317
ConfigurationRef,
2418
};
2519

@@ -834,32 +828,7 @@ extern "C" fn ANativeActivity_onCreate(
834828
saved_state_size: libc::size_t,
835829
) {
836830
abort_on_panic(|| {
837-
// Maybe make this stdout/stderr redirection an optional / opt-in feature?...
838-
let file = unsafe {
839-
let mut logpipe: [RawFd; 2] = Default::default();
840-
libc::pipe2(logpipe.as_mut_ptr(), libc::O_CLOEXEC);
841-
libc::dup2(logpipe[1], libc::STDOUT_FILENO);
842-
libc::dup2(logpipe[1], libc::STDERR_FILENO);
843-
libc::close(logpipe[1]);
844-
845-
File::from_raw_fd(logpipe[0])
846-
};
847-
848-
std::thread::spawn(move || {
849-
let tag = CStr::from_bytes_with_nul(b"RustStdoutStderr\0").unwrap();
850-
let mut reader = BufReader::new(file);
851-
let mut buffer = String::new();
852-
loop {
853-
buffer.clear();
854-
if let Ok(len) = reader.read_line(&mut buffer) {
855-
if len == 0 {
856-
break;
857-
} else if let Ok(msg) = CString::new(buffer.clone()) {
858-
android_log(Level::Info, tag, &msg);
859-
}
860-
}
861-
}
862-
});
831+
let _join_log_forwarder = forward_stdio_to_logcat();
863832

864833
log::trace!(
865834
"Creating: {:p}, saved_state = {:p}, save_state_size = {}",

android-activity/src/util.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
use log::Level;
1+
use log::{error, Level};
22
use std::{
33
ffi::{CStr, CString},
4-
os::raw::c_char,
4+
fs::File,
5+
io::{BufRead as _, BufReader, Result},
6+
os::{
7+
fd::{FromRawFd as _, RawFd},
8+
raw::c_char,
9+
},
510
};
611

712
pub fn try_get_path_from_ptr(path: *const c_char) -> Option<std::path::PathBuf> {
@@ -31,6 +36,44 @@ pub(crate) fn android_log(level: Level, tag: &CStr, msg: &CStr) {
3136
}
3237
}
3338

39+
pub(crate) fn forward_stdio_to_logcat() -> std::thread::JoinHandle<Result<()>> {
40+
// XXX: make this stdout/stderr redirection an optional / opt-in feature?...
41+
42+
let file = unsafe {
43+
let mut logpipe: [RawFd; 2] = Default::default();
44+
libc::pipe2(logpipe.as_mut_ptr(), libc::O_CLOEXEC);
45+
libc::dup2(logpipe[1], libc::STDOUT_FILENO);
46+
libc::dup2(logpipe[1], libc::STDERR_FILENO);
47+
libc::close(logpipe[1]);
48+
49+
File::from_raw_fd(logpipe[0])
50+
};
51+
52+
std::thread::Builder::new()
53+
.name("stdio-to-logcat".to_string())
54+
.spawn(move || -> Result<()> {
55+
let tag = CStr::from_bytes_with_nul(b"RustStdoutStderr\0").unwrap();
56+
let mut reader = BufReader::new(file);
57+
let mut buffer = String::new();
58+
loop {
59+
buffer.clear();
60+
let len = match reader.read_line(&mut buffer) {
61+
Ok(len) => len,
62+
Err(e) => {
63+
error!("Logcat forwarder failed to read stdin/stderr: {e:?}");
64+
break Err(e);
65+
}
66+
};
67+
if len == 0 {
68+
break Ok(());
69+
} else if let Ok(msg) = CString::new(buffer.clone()) {
70+
android_log(Level::Info, tag, &msg);
71+
}
72+
}
73+
})
74+
.expect("Failed to start stdout/stderr to logcat forwarder thread")
75+
}
76+
3477
pub(crate) fn log_panic(panic: Box<dyn std::any::Any + Send>) {
3578
let rust_panic = unsafe { CStr::from_bytes_with_nul_unchecked(b"RustPanic\0") };
3679

0 commit comments

Comments
 (0)