Нет вывода из нестандартного дескриптора файла - PullRequest
1 голос
/ 18 января 2020

У меня проблемы с получением данных от дочернего процесса.

Чтобы отправить строку в дочерний процесс, вы пишете в FD3, и он выведет результат в FD4.

* 1006. * Дочерний процесс работает нормально, и если он не может записать в FD4, процесс не запустится правильно, поэтому FD4 должен быть доступен, но я просто не знаю, почему не выводится.

Мои первоначальные мысли: при отправке строки (на FD3) она не заканчивалась нулевым байтом, поэтому неправильно получала строку (и затем не отправляла ничего обратно на FD4), но я уверена, что делаю это правильно.

Я проверил запись в FD4 внутри дочернего процесса вручную, и родительский файл получил вывод.

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();
}

Это открытые FD для дочернего процесса: 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

ОБНОВЛЕНИЕ

Я обнаружил проблему, по какой-то причине первый аргумент при запуске процесса chrome игнорировался ?? Поэтому, когда я помещаю любой другой аргумент в качестве первого в списке, chrome фактически запускает удаленную отладку. Странная проблема!

Когда я запускаю процесс chrome в терминале с --remote-debugging-pipe в качестве первого аргумента, он тоже работает нормально, так почему это происходит, когда я использую: execvp(&file, &args)

1 Ответ

0 голосов
/ 19 января 2020

Проблема в том, как я запускаю процесс.

execvp(&file, &args) требует, чтобы первым аргументом было местоположение файла. Спасибо: source

Изменение этого кода заставляет все работать как положено:

let args = vec![file.as_c_str(), arg1.as_c_str(),arg2.as_c_str()];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...