mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
ohos/android: Redirect stdout/stderr to log
sink (#32858)
* ohos: redirect stdout/stderr to logging sink Based on the existing android `redirect_stdout_to_logcat` implementation, but using the safe abstractions from `nix` and dumping to the `log` sink, instead of directly writing the log. Signed-off-by: Jonathan Schwender <jonathan.schwender@huawei.com> * android: Use new shared implementation for logcat redirection. Signed-off-by: Jonathan Schwender <jonathan.schwender@huawei.com> * servoshell: Register cfg(production) Signed-off-by: Jonathan Schwender <jonathan.schwender@huawei.com> * Update ports/servoshell/egl/log.rs Co-authored-by: Martin Robinson <mrobinson@igalia.com> Signed-off-by: Jonathan Schwender <55576758+jschwe@users.noreply.github.com> * Change info! to debug! to match original behavior on android Signed-off-by: Jonathan Schwender <jonathan.schwender@huawei.com> --------- Signed-off-by: Jonathan Schwender <jonathan.schwender@huawei.com> Signed-off-by: Jonathan Schwender <55576758+jschwe@users.noreply.github.com> Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
353ceb0ffb
commit
97c84b6127
8 changed files with 127 additions and 93 deletions
|
@ -93,6 +93,8 @@ pub extern "C" fn Java_org_servo_servoview_JNIServo_init<'local>(
|
|||
"servo",
|
||||
"servoshell",
|
||||
"servoshell::egl:gl_glue",
|
||||
// Show redirected stdout / stderr by default
|
||||
"servoshell::egl::log",
|
||||
// Show JS errors by default.
|
||||
"script::dom::bindings::error",
|
||||
// Show GL errors by default.
|
||||
|
@ -120,7 +122,12 @@ pub extern "C" fn Java_org_servo_servoview_JNIServo_init<'local>(
|
|||
|
||||
info!("init");
|
||||
|
||||
redirect_stdout_to_logcat();
|
||||
// We only redirect stdout and stderr for non-production builds, since it is
|
||||
// only used for debugging purposes. This saves us one thread in production.
|
||||
#[cfg(not(production))]
|
||||
if let Err(e) = super::log::redirect_stdout_and_stderr() {
|
||||
error!("Failed to redirect stdout and stderr to logcat due to: {e:?}");
|
||||
}
|
||||
|
||||
let callbacks_ref = match env.new_global_ref(callbacks_obj) {
|
||||
Ok(r) => r,
|
||||
|
@ -692,91 +699,6 @@ extern "C" {
|
|||
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 = c"servoshell".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 {
|
||||
unsafe {
|
||||
__android_log_write(
|
||||
3,
|
||||
tag,
|
||||
c"error in log thread; closing".as_ptr() as *const _,
|
||||
);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
result as usize + cursor
|
||||
};
|
||||
|
||||
// Only modify the portion of the buffer that contains real data.
|
||||
let buf = &mut buf[0..end];
|
||||
|
||||
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 end == 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;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn throw(env: &mut JNIEnv, err: &str) {
|
||||
if let Err(e) = env.throw(("java/lang/Exception", err)) {
|
||||
warn!(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue