Skip to content

Commit ce4413b

Browse files
MarijnS95rib
authored andcommitted
Close logpipe input file descriptor after dup2()
When the input file descriptor of the `pipe()` is `dup2()`'d into `stdin` and `stdout` it is effectively copied, leaving the original file descriptor open and leaking at the end of these statements. Only the output file descriptor has its ownership transferred to `File` and will be cleaned up properly. This should cause the reading end to read EOF and return zero bytes when `stdin` and `stdout` is open, rather than remaining open "indefinitely" (barring the whole process being taken down) as there will always be that one file descriptor referencing the input end of the pipe.
1 parent a291e37 commit ce4413b

File tree

2 files changed

+31
-22
lines changed

2 files changed

+31
-22
lines changed

android-activity/src/game_activity/mod.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -912,13 +912,19 @@ extern "Rust" {
912912
pub unsafe extern "C" fn _rust_glue_entry(native_app: *mut ffi::android_app) {
913913
abort_on_panic(|| {
914914
// Maybe make this stdout/stderr redirection an optional / opt-in feature?...
915-
let mut logpipe: [RawFd; 2] = Default::default();
916-
libc::pipe(logpipe.as_mut_ptr());
917-
libc::dup2(logpipe[1], libc::STDOUT_FILENO);
918-
libc::dup2(logpipe[1], libc::STDERR_FILENO);
915+
916+
let file = {
917+
let mut logpipe: [RawFd; 2] = Default::default();
918+
libc::pipe2(logpipe.as_mut_ptr(), libc::O_CLOEXEC);
919+
libc::dup2(logpipe[1], libc::STDOUT_FILENO);
920+
libc::dup2(logpipe[1], libc::STDERR_FILENO);
921+
libc::close(logpipe[1]);
922+
923+
File::from_raw_fd(logpipe[0])
924+
};
925+
919926
thread::spawn(move || {
920927
let tag = CStr::from_bytes_with_nul(b"RustStdoutStderr\0").unwrap();
921-
let file = File::from_raw_fd(logpipe[0]);
922928
let mut reader = BufReader::new(file);
923929
let mut buffer = String::new();
924930
loop {

android-activity/src/native_activity/glue.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -835,28 +835,31 @@ extern "C" fn ANativeActivity_onCreate(
835835
) {
836836
abort_on_panic(|| {
837837
// Maybe make this stdout/stderr redirection an optional / opt-in feature?...
838-
unsafe {
838+
let file = unsafe {
839839
let mut logpipe: [RawFd; 2] = Default::default();
840-
libc::pipe(logpipe.as_mut_ptr());
840+
libc::pipe2(logpipe.as_mut_ptr(), libc::O_CLOEXEC);
841841
libc::dup2(logpipe[1], libc::STDOUT_FILENO);
842842
libc::dup2(logpipe[1], libc::STDERR_FILENO);
843-
std::thread::spawn(move || {
844-
let tag = CStr::from_bytes_with_nul(b"RustStdoutStderr\0").unwrap();
845-
let file = File::from_raw_fd(logpipe[0]);
846-
let mut reader = BufReader::new(file);
847-
let mut buffer = String::new();
848-
loop {
849-
buffer.clear();
850-
if let Ok(len) = reader.read_line(&mut buffer) {
851-
if len == 0 {
852-
break;
853-
} else if let Ok(msg) = CString::new(buffer.clone()) {
854-
android_log(Level::Info, tag, &msg);
855-
}
843+
libc::close(logpipe[1]);
844+
845+
File::from_raw_fd(logpipe[0])
846+
};
847+
848+
std::thread::spawn(move || {
849+
let tag = CStr::from_bytes_with_nul(b"RustStdoutStderr\0").unwrap();
850+
let mut reader = BufReader::new(file);
851+
let mut buffer = String::new();
852+
loop {
853+
buffer.clear();
854+
if let Ok(len) = reader.read_line(&mut buffer) {
855+
if len == 0 {
856+
break;
857+
} else if let Ok(msg) = CString::new(buffer.clone()) {
858+
android_log(Level::Info, tag, &msg);
856859
}
857860
}
858-
});
859-
}
861+
}
862+
});
860863

861864
log::trace!(
862865
"Creating: {:p}, saved_state = {:p}, save_state_size = {}",

0 commit comments

Comments
 (0)