Rewrite android logging to use checked slices.

This commit is contained in:
Josh Matthews 2018-09-26 11:00:11 -04:00
parent f402dd9ecf
commit b11f071976

View file

@ -14,7 +14,6 @@ use libc::{pipe, dup2, read};
use log::Level;
use std;
use std::borrow::Cow;
use std::ffi::CString;
use std::os::raw::{c_char, c_int, c_void};
use std::sync::{Arc, Mutex};
use std::thread;
@ -466,51 +465,57 @@ fn redirect_stdout_to_logcat() {
// 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 || {
unsafe {
let mut buf: Vec<c_char> = Vec::with_capacity(512);
let mut cursor = 0_usize;
const BUF_LENGTH: usize = 512;
let mut buf = vec![b'\0' as c_char; BUF_LENGTH];
// TODO: shouldn't use Rust stdlib
let tag = CString::new("simpleservo").unwrap();
let tag = tag.as_ptr();
// Always keep at least one null terminator
const BUF_AVAILABLE: usize = BUF_LENGTH - 1;
let buf = &mut buf[..BUF_AVAILABLE];
loop {
let result = read(descriptor, buf.as_mut_ptr().offset(cursor as isize) as *mut _,
buf.capacity() - 1 - cursor);
let mut cursor = 0_usize;
let len = if result == 0 {
return;
} else if result < 0 {
return; /* TODO: report problem */
} else {
result as usize + cursor
};
let tag = b"simpleservo\0".as_ptr() as _;
buf.set_len(len);
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;
__android_log_write(3, tag, buf.as_ptr());
if last_newline_pos < buf.len() - 1 {
let last_newline_pos = last_newline_pos + 1;
cursor = buf.len() - last_newline_pos;
debug_assert!(cursor < buf.capacity());
for j in 0..cursor as usize {
buf[j] = buf[last_newline_pos + j];
}
buf[cursor] = b'\0' as c_char;
buf.set_len(cursor + 1);
} else {
cursor = 0;
}
} else {
cursor = buf.len();
loop {
let result = {
let read_into = &mut buf[cursor..];
unsafe {
read(descriptor, read_into.as_mut_ptr() as *mut _, read_into.len())
}
if cursor == buf.capacity() - 1 {
};
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());
buf.set_len(0);
}
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;
}
}
});