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 log::Level;
use std; use std;
use std::borrow::Cow; use std::borrow::Cow;
use std::ffi::CString;
use std::os::raw::{c_char, c_int, 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; use std::thread;
@ -466,19 +465,26 @@ fn redirect_stdout_to_logcat() {
// 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.
let _detached = thread::spawn(move || { let _detached = thread::spawn(move || {
unsafe { const BUF_LENGTH: usize = 512;
let mut buf: Vec<c_char> = Vec::with_capacity(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 mut cursor = 0_usize;
// TODO: shouldn't use Rust stdlib let tag = b"simpleservo\0".as_ptr() as _;
let tag = CString::new("simpleservo").unwrap();
let tag = tag.as_ptr();
loop { loop {
let result = read(descriptor, buf.as_mut_ptr().offset(cursor as isize) as *mut _, let result = {
buf.capacity() - 1 - cursor); let read_into = &mut buf[cursor..];
unsafe {
read(descriptor, read_into.as_mut_ptr() as *mut _, read_into.len())
}
};
let len = if result == 0 { let end = if result == 0 {
return; return;
} else if result < 0 { } else if result < 0 {
return; /* TODO: report problem */ return; /* TODO: report problem */
@ -486,31 +492,30 @@ fn redirect_stdout_to_logcat() {
result as usize + cursor result as usize + cursor
}; };
buf.set_len(len);
if let Some(last_newline_pos) = buf.iter().rposition(|&c| c == b'\n' as c_char) { 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; buf[last_newline_pos] = b'\0' as c_char;
unsafe {
__android_log_write(3, tag, buf.as_ptr()); __android_log_write(3, tag, buf.as_ptr());
}
if last_newline_pos < buf.len() - 1 { if last_newline_pos < buf.len() - 1 {
let last_newline_pos = last_newline_pos + 1; let pos_after_newline = last_newline_pos + 1;
cursor = buf.len() - last_newline_pos; let len_not_logged_yet = buf[pos_after_newline..].len();
debug_assert!(cursor < buf.capacity()); for j in 0..len_not_logged_yet as usize {
for j in 0..cursor as usize { buf[j] = buf[pos_after_newline + j];
buf[j] = buf[last_newline_pos + j];
} }
buf[cursor] = b'\0' as c_char; cursor = len_not_logged_yet;
buf.set_len(cursor + 1);
} else { } else {
cursor = 0; cursor = 0;
} }
} else { } else if cursor == BUF_AVAILABLE {
cursor = buf.len(); // 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.
if cursor == buf.capacity() - 1 { unsafe {
__android_log_write(3, tag, buf.as_ptr()); __android_log_write(3, tag, buf.as_ptr());
buf.set_len(0);
cursor = 0;
} }
cursor = 0;
} else {
cursor = end;
} }
} }
}); });