Use Rust stdlib threads for android logging.

This commit is contained in:
Josh Matthews 2018-09-26 10:54:43 -04:00
parent 38d3f59170
commit f402dd9ecf

View file

@ -10,14 +10,14 @@ use gl_glue;
use jni::{JNIEnv, JavaVM}; use jni::{JNIEnv, JavaVM};
use jni::objects::{GlobalRef, JClass, JObject, JString, JValue}; use jni::objects::{GlobalRef, JClass, JObject, JString, JValue};
use jni::sys::{jboolean, jfloat, jint, jstring, JNI_TRUE}; use jni::sys::{jboolean, jfloat, jint, jstring, JNI_TRUE};
use libc::{pipe, dup2, read};
use log::Level; use log::Level;
use std; use std;
use std::borrow::Cow; use std::borrow::Cow;
use std::ffi::CString; use std::ffi::CString;
use std::mem; use std::os::raw::{c_char, c_int, c_void};
use std::os::raw::{c_char, c_int, c_long, c_void};
use std::ptr;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::thread;
struct HostCallbacks { struct HostCallbacks {
callbacks: GlobalRef, callbacks: GlobalRef,
@ -447,38 +447,26 @@ fn initialize_android_glue(env: &JNIEnv, activity: JObject) {
} }
} }
#[allow(non_camel_case_types)]
type pthread_t = c_long;
#[allow(non_camel_case_types)]
type pthread_mutexattr_t = c_long;
#[allow(non_camel_case_types)]
type pthread_attr_t = c_void; // FIXME: wrong
extern { extern {
fn pipe(_: *mut c_int) -> c_int;
fn dup2(fildes: c_int, fildes2: c_int) -> c_int;
fn read(fd: c_int, buf: *mut c_void, count: usize) -> isize;
fn pthread_create(_: *mut pthread_t, _: *const pthread_attr_t,
_: extern fn(*mut c_void) -> *mut c_void, _: *mut c_void) -> c_int;
fn pthread_detach(thread: pthread_t) -> c_int;
pub fn __android_log_write(prio: c_int, tag: *const c_char, text: *const c_char) -> c_int; pub fn __android_log_write(prio: c_int, tag: *const c_char, text: *const c_char) -> c_int;
} }
fn redirect_stdout_to_logcat() { fn redirect_stdout_to_logcat() {
// The first step is to redirect stdout and stderr to the logs. // The first step is to redirect stdout and stderr to the logs.
unsafe {
// We redirect stdout and stderr to a custom descriptor. // We redirect stdout and stderr to a custom descriptor.
let mut pfd: [c_int; 2] = [0, 0]; let mut pfd: [c_int; 2] = [0, 0];
unsafe {
pipe(pfd.as_mut_ptr()); pipe(pfd.as_mut_ptr());
dup2(pfd[1], 1); dup2(pfd[1], 1);
dup2(pfd[1], 2); dup2(pfd[1], 2);
}
let descriptor = pfd[0];
// Then we spawn a thread whose only job is to read from the other side of the // Then we spawn a thread whose only job is to read from the other side of the
// pipe and redirect to the logs. // pipe and redirect to the logs.
extern fn logging_thread(descriptor: *mut c_void) -> *mut c_void { let _detached = thread::spawn(move || {
unsafe { unsafe {
let descriptor = descriptor as usize as c_int;
let mut buf: Vec<c_char> = Vec::with_capacity(512); let mut buf: Vec<c_char> = Vec::with_capacity(512);
let mut cursor = 0_usize; let mut cursor = 0_usize;
@ -491,9 +479,9 @@ fn redirect_stdout_to_logcat() {
buf.capacity() - 1 - cursor); buf.capacity() - 1 - cursor);
let len = if result == 0 { let len = if result == 0 {
return ptr::null_mut(); return;
} else if result < 0 { } else if result < 0 {
return ptr::null_mut(); /* TODO: report problem */ return; /* TODO: report problem */
} else { } else {
result as usize + cursor result as usize + cursor
}; };
@ -525,13 +513,5 @@ fn redirect_stdout_to_logcat() {
} }
} }
} }
} });
let mut thread = mem::uninitialized();
let result = pthread_create(&mut thread, ptr::null(), logging_thread,
pfd[0] as usize as *mut c_void);
assert_eq!(result, 0);
let result = pthread_detach(thread);
assert_eq!(result, 0);
}
} }