I am having issues receiving data from the child process.
To send a string to the child process you write to FD3
and it will output the result to FD4
.
The child process runs fine, and if it couldn't write to FD4
, the process would not start correctly, so FD4
has to be available but I just don't know why no output is given.
My initial thoughts is when sending the string (to FD3
) it wasn't null byte terminating therefore not receiving the string correctly (and then not sending anything back on FD4
) but I am sure I am doing it correctly.
I have tested writing to FD4
within the child process manually and the parent receives the output.
use nix::fcntl::FcntlArg::{F_SETFD};
use nix::fcntl::{fcntl, open, FdFlag, OFlag};
use nix::sys::socket::{socketpair, AddressFamily, SockFlag, SockType};
use nix::sys::stat::Mode;
use nix::unistd::{close, dup2, execvp, fork, pipe, read, write, ForkResult};
use std::ffi::CString;
use std::os::unix::io::RawFd;
use std::process::abort;
fn main() {
let input_socket: (RawFd, RawFd) = create_socket();
let output_socket: (RawFd, RawFd) = create_socket();
match fork() {
Ok(ForkResult::Parent { child, .. }) => {
println!("Child PID: {}", child);
close(input_socket.1).unwrap();
close(output_socket.1).unwrap();
let test = r#"{"id":0,"method":"Target.getTargets"}\0"#;
write(input_socket.0, test.as_bytes()).expect("unable to write");
let mut buf = [0; 64];
read(output_socket.0, &mut buf).unwrap();
println!("BUFFER: {:#?}", std::str::from_utf8(&buf).unwrap());
}
Ok(ForkResult::Child) => {
setup_child(input_socket.1, output_socket.1);
abort()
}
Err(err) => { println!("{}", err); abort()},
}
}
#[cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "emscripten",
target_os = "freebsd",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd"
))]
fn create_socket() -> (RawFd, RawFd) {
socketpair(
AddressFamily::Unix,
SockType::Stream,
None,
SockFlag::SOCK_CLOEXEC,
)
.unwrap()
}
#[cfg(any(target_os = "ios", target_os = "macos"))]
fn create_socket() -> (RawFd, RawFd) {
let socket = socketpair(
AddressFamily::Unix,
SockType::Stream,
None,
SockFlag::empty(),
)
.unwrap();
fcntl(socket.0, F_SETFD(FdFlag::FD_CLOEXEC)).unwrap();
fcntl(socket.1, F_SETFD(FdFlag::FD_CLOEXEC)).unwrap();
socket
}
fn setup_child(input: RawFd, output: RawFd) {
let _input: RawFd = dup2(input, 3).unwrap();
let _output: RawFd = dup2(output, 4).unwrap();
let file = CString::new("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome").unwrap();
let arg1 = CString::new("--remote-debugging-pipe").unwrap();
let arg2 = CString::new("--enable-logging=stderr").unwrap();
let args = vec![arg1.as_c_str(),arg2.as_c_str()];
let _res = execvp(&file, &args).unwrap();
}
This is the open FDs for the child process: lsof -p 14620
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Chrome 14620 tom 0 PIPE 0xcafab653bf79be56 16384 ->0xfc41206e43b6bb9d
Chrome 14620 tom 1 PIPE 0x71c3c6a8bffbf5ad 16384 ->0x587f975b5bfd4499
Chrome 14620 tom 2 PIPE 0x71c3c6a8bffbf5ad 16384 ->0x587f975b5bfd4499
Chrome 14620 tom 3u unix 0x36cd3ac44c49d68d 0t0 ->0x36cd3ac44c49f2ad
Chrome 14620 tom 4u unix 0x36cd3ac44c49dc05 0t0 ->0x36cd3ac44c49f9b5
UPDATE
I found the issue, for some reason the first argument when running the chrome process was being ignored?? So when I place any other argument as the first in the list chrome actually starts up the remote debugging. Weird issue!
When I run the chrome process in terminal with --remote-debugging-pipe
as the first argument it works fine too, so why does it happen when i use: execvp(&file, &args)