mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Auto merge of #21812 - jdm:useful-output, r=SimonSapin
Provide useful defaults for Android logcat output
These changes integrate the stdout/stderr redirection from 0e80cfbcee/cargo-apk/injected-glue/lib.rs (L240-L303)
, and set up the default RUST_LOG filters so that useful JS errors and GL errors appear in the logcat output. I have verified that thread panics appear in output as well (without backtraces, sadly) by visiting https://acid3.acidtests.org.
---
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #21637 and fix #21783
- [x] These changes do not require tests because no tests for logcat.
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21812)
<!-- Reviewable:end -->
This commit is contained in:
commit
515afac456
1 changed files with 92 additions and 6 deletions
|
@ -10,11 +10,13 @@ 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::os::raw::c_void;
|
use std::os::raw::{c_char, c_int, c_void};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
struct HostCallbacks {
|
struct HostCallbacks {
|
||||||
callbacks: GlobalRef,
|
callbacks: GlobalRef,
|
||||||
|
@ -61,11 +63,19 @@ pub fn Java_com_mozilla_servoview_JNIServo_init(
|
||||||
// Note: Android debug logs are stripped from a release build.
|
// Note: Android debug logs are stripped from a release build.
|
||||||
// debug!() will only show in a debug build. Use info!() if logs
|
// debug!() will only show in a debug build. Use info!() if logs
|
||||||
// should show up in adb logcat with a release build.
|
// should show up in adb logcat with a release build.
|
||||||
let mut filter = Filter::default()
|
let filters = [
|
||||||
.with_min_level(Level::Debug)
|
"simpleservo::api",
|
||||||
.with_allowed_module_path("simpleservo::api")
|
"simpleservo::jniapi",
|
||||||
.with_allowed_module_path("simpleservo::jniapi")
|
"simpleservo::gl_glue::egl",
|
||||||
.with_allowed_module_path("simpleservo::gl_glue::egl");
|
// Show JS errors by default.
|
||||||
|
"script::dom::bindings::error",
|
||||||
|
// Show GL errors by default.
|
||||||
|
"canvas::webgl_thread",
|
||||||
|
];
|
||||||
|
let mut filter = Filter::default().with_min_level(Level::Debug);
|
||||||
|
for &module in &filters {
|
||||||
|
filter = filter.with_allowed_module_path(module);
|
||||||
|
}
|
||||||
let log_str = env.get_string(log_str).ok();
|
let log_str = env.get_string(log_str).ok();
|
||||||
let log_str = log_str.as_ref().map_or(Cow::Borrowed(""), |s| s.to_string_lossy());
|
let log_str = log_str.as_ref().map_or(Cow::Borrowed(""), |s| s.to_string_lossy());
|
||||||
for module in log_str.split(',') {
|
for module in log_str.split(',') {
|
||||||
|
@ -77,6 +87,7 @@ pub fn Java_com_mozilla_servoview_JNIServo_init(
|
||||||
info!("init");
|
info!("init");
|
||||||
|
|
||||||
initialize_android_glue(&env, activity);
|
initialize_android_glue(&env, activity);
|
||||||
|
redirect_stdout_to_logcat();
|
||||||
|
|
||||||
let args = env.get_string(args)
|
let args = env.get_string(args)
|
||||||
.expect("Couldn't get java string")
|
.expect("Couldn't get java string")
|
||||||
|
@ -434,3 +445,78 @@ fn initialize_android_glue(env: &JNIEnv, activity: JObject) {
|
||||||
ANDROID_APP = Box::into_raw(Box::new(app));
|
ANDROID_APP = Box::into_raw(Box::new(app));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern {
|
||||||
|
pub fn __android_log_write(prio: c_int, tag: *const c_char, text: *const c_char) -> c_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn redirect_stdout_to_logcat() {
|
||||||
|
// The first step is to redirect stdout and stderr to the logs.
|
||||||
|
// We redirect stdout and stderr to a custom descriptor.
|
||||||
|
let mut pfd: [c_int; 2] = [0, 0];
|
||||||
|
unsafe {
|
||||||
|
pipe(pfd.as_mut_ptr());
|
||||||
|
dup2(pfd[1], 1);
|
||||||
|
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
|
||||||
|
// pipe and redirect to the logs.
|
||||||
|
let _detached = thread::spawn(move || {
|
||||||
|
const BUF_LENGTH: usize = 512;
|
||||||
|
let mut buf = vec![b'\0' as c_char; BUF_LENGTH];
|
||||||
|
|
||||||
|
// Always keep at least one null terminator
|
||||||
|
const BUF_AVAILABLE: usize = BUF_LENGTH - 1;
|
||||||
|
let buf = &mut buf[..BUF_AVAILABLE];
|
||||||
|
|
||||||
|
let mut cursor = 0_usize;
|
||||||
|
|
||||||
|
let tag = b"simpleservo\0".as_ptr() as _;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let result = {
|
||||||
|
let read_into = &mut buf[cursor..];
|
||||||
|
unsafe {
|
||||||
|
read(descriptor, read_into.as_mut_ptr() as *mut _, read_into.len())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let end = if result == 0 {
|
||||||
|
return;
|
||||||
|
} else if result < 0 {
|
||||||
|
return; /* TODO: report problem */
|
||||||
|
} else {
|
||||||
|
result as usize + cursor
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(last_newline_pos) = buf.iter().rposition(|&c| c == b'\n' as c_char) {
|
||||||
|
buf[last_newline_pos] = b'\0' as c_char;
|
||||||
|
unsafe {
|
||||||
|
__android_log_write(3, tag, buf.as_ptr());
|
||||||
|
}
|
||||||
|
if last_newline_pos < buf.len() - 1 {
|
||||||
|
let pos_after_newline = last_newline_pos + 1;
|
||||||
|
let len_not_logged_yet = buf[pos_after_newline..].len();
|
||||||
|
for j in 0..len_not_logged_yet as usize {
|
||||||
|
buf[j] = buf[pos_after_newline + j];
|
||||||
|
}
|
||||||
|
cursor = len_not_logged_yet;
|
||||||
|
} else {
|
||||||
|
cursor = 0;
|
||||||
|
}
|
||||||
|
} else if cursor == BUF_AVAILABLE {
|
||||||
|
// No newline found but the buffer is full, flush it anyway.
|
||||||
|
// `buf.as_ptr()` is null-terminated by BUF_LENGTH being 1 less than BUF_AVAILABLE.
|
||||||
|
unsafe {
|
||||||
|
__android_log_write(3, tag, buf.as_ptr());
|
||||||
|
}
|
||||||
|
cursor = 0;
|
||||||
|
} else {
|
||||||
|
cursor = end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue