mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Auto merge of #23922 - angelortiz1007:redir, r=jdm
Redirect stdout/stderr on windows Added function redirect_stdout_stderr() to support stdout & stderr to be redirected to OutputDebugStringA(). --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `23734` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #23734 (GitHub issue number if applicable) <!-- Either: --> - [X] There are tests for these changes OR Functionality was verified by adding logic in unsafe fn init(). By building and running ServoApp, If redirect_stdout_stderr() failed, a warn!() message would be sent to the "output" window of VS2007 with the GetLastError() value. If the function redirect_stdout_stderr() succeeded, the println!("Capi/lib.rs: init() function called redirect_stdout_stderr() successfully.\n") output would be seen in the "output" window of VS2007. - [ ] These changes do not require tests because ___ <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- 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/23922) <!-- Reviewable:end -->
This commit is contained in:
commit
b3c0ed295f
4 changed files with 135 additions and 1 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -4612,8 +4612,10 @@ version = "0.0.1"
|
|||
dependencies = [
|
||||
"cbindgen 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"simpleservo 0.0.1",
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -74,7 +74,7 @@ sig = "1.0"
|
|||
x11 = "2.0.0"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
winapi = { version = "0.3", features = ["wingdi", "winuser"] }
|
||||
winapi = { version = "0.3", features = ["wingdi", "winuser", "winnt", "winbase", "processenv", "namedpipeapi", "ntdef", "minwindef", "handleapi", "debugapi"] }
|
||||
|
||||
[target.'cfg(any(target_os = "macos", all(target_arch = "x86_64", target_os = "linux")))'.dependencies]
|
||||
osmesa-src = {git = "https://github.com/servo/osmesa-src"}
|
||||
|
|
|
@ -17,6 +17,10 @@ simpleservo = { path = "../api" }
|
|||
log = "0.4"
|
||||
env_logger = "0.6"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
libc = "0.2"
|
||||
winapi = {version = "0.3", features = ["wingdi", "winuser", "winnt", "winbase", "processenv", "namedpipeapi", "ntdef", "minwindef", "handleapi", "debugapi"]}
|
||||
|
||||
[build-dependencies]
|
||||
cbindgen = "0.8"
|
||||
|
||||
|
|
|
@ -22,6 +22,130 @@ fn catch_any_panic<F: FnOnce() + UnwindSafe>(function: F) -> bool {
|
|||
panic::catch_unwind(function).is_ok()
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
fn redirect_stdout_stderr() -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn redirect_stdout_stderr() -> Result<(), String> {
|
||||
do_redirect_stdout_stderr().map_err(|()| {
|
||||
format!("GetLastError() = {}", unsafe {
|
||||
winapi::um::errhandlingapi::GetLastError()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
// Function to redirect STDOUT (1) and STDERR(2) to Windows API
|
||||
// OutputDebugString().
|
||||
// Return Value: Result<(), String>
|
||||
// Ok() - stdout and stderr redirects.
|
||||
// Err(str) - The Err value can contain the string value of GetLastError.
|
||||
fn do_redirect_stdout_stderr() -> Result<(), ()> {
|
||||
use std::thread;
|
||||
use winapi::shared;
|
||||
use winapi::um::debugapi;
|
||||
use winapi::um::handleapi;
|
||||
use winapi::um::minwinbase;
|
||||
use winapi::um::namedpipeapi;
|
||||
use winapi::um::processenv;
|
||||
use winapi::um::winbase;
|
||||
use winapi::um::winnt;
|
||||
|
||||
let mut h_read_pipe: winnt::HANDLE = handleapi::INVALID_HANDLE_VALUE;
|
||||
let mut h_write_pipe: winnt::HANDLE = handleapi::INVALID_HANDLE_VALUE;
|
||||
let mut secattr: minwinbase::SECURITY_ATTRIBUTES = unsafe { mem::zeroed() };
|
||||
const BUF_LENGTH: usize = 1024;
|
||||
|
||||
secattr.nLength = mem::size_of::<minwinbase::SECURITY_ATTRIBUTES>() as u32;
|
||||
secattr.bInheritHandle = shared::minwindef::TRUE;
|
||||
secattr.lpSecurityDescriptor = shared::ntdef::NULL;
|
||||
|
||||
unsafe {
|
||||
if namedpipeapi::CreatePipe(
|
||||
&mut h_read_pipe,
|
||||
&mut h_write_pipe,
|
||||
&mut secattr,
|
||||
BUF_LENGTH as u32,
|
||||
) == 0
|
||||
{
|
||||
return Err(());
|
||||
}
|
||||
|
||||
if processenv::SetStdHandle(winbase::STD_OUTPUT_HANDLE, h_write_pipe) == 0 ||
|
||||
processenv::SetStdHandle(winbase::STD_ERROR_HANDLE, h_write_pipe) == 0
|
||||
{
|
||||
return Err(());
|
||||
}
|
||||
|
||||
if handleapi::SetHandleInformation(
|
||||
h_read_pipe,
|
||||
winbase::HANDLE_FLAG_INHERIT,
|
||||
winbase::HANDLE_FLAG_INHERIT,
|
||||
) == 0 ||
|
||||
handleapi::SetHandleInformation(
|
||||
h_write_pipe,
|
||||
winbase::HANDLE_FLAG_INHERIT,
|
||||
winbase::HANDLE_FLAG_INHERIT,
|
||||
) == 0
|
||||
{
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let h_read_pipe_fd = libc::open_osfhandle(h_read_pipe as libc::intptr_t, libc::O_RDONLY);
|
||||
let h_write_pipe_fd = libc::open_osfhandle(h_write_pipe as libc::intptr_t, libc::O_WRONLY);
|
||||
|
||||
if h_read_pipe_fd == -1 || h_write_pipe_fd == -1 {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
// 0 indicates success.
|
||||
if libc::dup2(h_write_pipe_fd, 1) != 0 || libc::dup2(h_write_pipe_fd, 2) != 0 {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
// If SetStdHandle(winbase::STD_OUTPUT_HANDLE, hWritePipe) is not called prior,
|
||||
// this will fail. GetStdHandle() is used to make certain "servo" has the stdout
|
||||
// file descriptor associated.
|
||||
let h_stdout = processenv::GetStdHandle(winbase::STD_OUTPUT_HANDLE);
|
||||
if h_stdout == handleapi::INVALID_HANDLE_VALUE || h_stdout == shared::ntdef::NULL {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
// If SetStdHandle(winbase::STD_ERROR_HANDLE, hWritePipe) is not called prior,
|
||||
// this will fail. GetStdHandle() is used to make certain "servo" has the stderr
|
||||
// file descriptor associated.
|
||||
let h_stderr = processenv::GetStdHandle(winbase::STD_ERROR_HANDLE);
|
||||
if h_stderr == handleapi::INVALID_HANDLE_VALUE || h_stderr == shared::ntdef::NULL {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
// Spawn a thread. The thread will redirect all STDOUT and STDERR messages
|
||||
// to OutputDebugString()
|
||||
let _handler = thread::spawn(move || {
|
||||
loop {
|
||||
let mut read_buf: [i8; BUF_LENGTH] = [0; BUF_LENGTH];
|
||||
|
||||
let result = libc::read(
|
||||
h_read_pipe_fd,
|
||||
read_buf.as_mut_ptr() as *mut _,
|
||||
read_buf.len() as u32 - 1,
|
||||
);
|
||||
|
||||
if result == -1 {
|
||||
break;
|
||||
}
|
||||
|
||||
// Write to Debug port.
|
||||
debugapi::OutputDebugStringA(read_buf.as_mut_ptr() as winnt::LPSTR);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn call<F>(f: F)
|
||||
where
|
||||
F: Fn(&mut ServoGlue) -> Result<(), &'static str>,
|
||||
|
@ -117,6 +241,10 @@ unsafe fn init(
|
|||
) {
|
||||
init_logger();
|
||||
|
||||
if let Err(reason) = redirect_stdout_stderr() {
|
||||
warn!("Error redirecting stdout/stderr: {}", reason);
|
||||
}
|
||||
|
||||
let args = if !opts.args.is_null() {
|
||||
let args = CStr::from_ptr(opts.args);
|
||||
args.to_str()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue