Function nc::pidfd_getfd

source ·
pub unsafe fn pidfd_getfd(
    pidfd: i32,
    target_fd: i32,
    flags: u32
) -> Result<i32, Errno>
Expand description

Obtain a duplicate of another process’s file descriptor.

§Example

let pid = unsafe { nc::fork() };
const STDOUT_FD: i32 = 1;
assert!(pid.is_ok());
if pid == Ok(0) {
    println!("In child process, pid: {}", unsafe { nc::getpid() });
    let path = "/tmp/nc-pidfdopen";
    let fd = unsafe {
        nc::openat(
            nc::AT_FDCWD,
            path,
            nc::O_CREAT | nc::O_WRONLY | nc::O_TRUNC,
            0o644,
        )
    };
    assert!(fd.is_ok());
    let fd = fd.unwrap();
    let ret = unsafe { nc::dup3(fd, STDOUT_FD, 0) };
    assert!(ret.is_ok());
    println!("[child] stdout redirected to file!");

    let t = nc::timespec_t {
        tv_sec: 2,
        tv_nsec: 0,
    };
    unsafe {
        let ret = nc::nanosleep(&t, None);
        assert!(ret.is_ok());
        let ret = nc::close(fd);
        assert!(ret.is_ok());
        let ret = nc::unlinkat(nc::AT_FDCWD, path, 0);
        assert!(ret.is_ok());
        nc::exit(0);
    }
}

let pid = pid.unwrap();
println!("[parent] child pid: {}", pid);

let t = nc::timespec_t {
    tv_sec: 2,
    tv_nsec: 0,
};
let ret = unsafe { nc::nanosleep(&t, None) };
assert!(ret.is_ok());

let pidfd = unsafe { nc::pidfd_open(pid, 0) };
if pidfd == Err(nc::errno::ENOSYS) {
    eprintln!("PIDFD_OPEN syscall not supported in this system");
    return;
}
let pidfd = pidfd.unwrap();

let child_stdout_fd = unsafe { nc::pidfd_getfd(pidfd, STDOUT_FD, 0) };
if child_stdout_fd == Err(nc::errno::ENOSYS) {
    eprintln!("PIDFD_OPEN syscall not supported in this system");
    return;
}
let child_stdout_fd = child_stdout_fd.unwrap();
let msg = "Hello, msg from parent process\n";
let ret = unsafe { nc::write(child_stdout_fd, msg.as_ptr() as usize, msg.len()) };
assert!(ret.is_ok());
let nwrite = ret.unwrap();
assert_eq!(nwrite as usize, msg.len());

let ret = unsafe { nc::close(pidfd) };
assert!(ret.is_ok());
let ret = unsafe { nc::close(child_stdout_fd) };
assert!(ret.is_ok());
Examples found in repository?
examples/pidfd.rs (line 73)
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
fn run_main() {
    const STDOUT_FD: i32 = 1;

    let pid = unsafe { nc::fork() };
    assert!(pid.is_ok());
    if pid == Ok(0) {
        let curr_pid = unsafe { nc::getpid() };
        println!("In child process, pid: {}", curr_pid);
        let path = "/tmp/nc-pidfdopen";
        let fd = unsafe {
            nc::openat(
                nc::AT_FDCWD,
                path,
                nc::O_CREAT | nc::O_WRONLY | nc::O_TRUNC,
                0o644,
            )
        };
        assert!(fd.is_ok());
        let fd = fd.unwrap();
        let ret = unsafe { nc::dup3(fd, STDOUT_FD, 0) };
        assert!(ret.is_ok());
        println!("[child] stdout redirected to file!");

        let t = nc::timespec_t {
            tv_sec: 2,
            tv_nsec: 0,
        };
        unsafe {
            let ret = nc::nanosleep(&t, None);
            assert!(ret.is_ok());
            let ret = nc::close(fd);
            assert!(ret.is_ok());
            let ret = nc::unlinkat(nc::AT_FDCWD, path, 0);
            assert!(ret.is_ok());
            nc::exit(0);
        }
    }

    let pid = pid.unwrap();
    println!("[parent] child pid: {}", pid);

    let t = nc::timespec_t {
        tv_sec: 2,
        tv_nsec: 0,
    };
    let ret = unsafe { nc::nanosleep(&t, None) };
    assert!(ret.is_ok());

    let pidfd = unsafe { nc::pidfd_open(pid, 0) };
    assert!(pidfd.is_ok());
    let pidfd = pidfd.unwrap();

    let ret = unsafe { nc::pidfd_getfd(pidfd, STDOUT_FD, 0) };
    println!("ret: {:?}", ret);
    if let Err(errno) = ret {
        eprintln!("pidfd_getfd() failed, err: {}", nc::strerror(errno));
    }
    let child_stdout_fd = ret.unwrap();
    let msg = "Hello, msg from parent process\n";
    let ret = unsafe { nc::write(child_stdout_fd, msg.as_ptr() as usize, msg.len()) };
    assert!(ret.is_ok());
    let nwrite = ret.unwrap();
    assert_eq!(nwrite as usize, msg.len());

    let mut info = nc::siginfo_t::default();
    let ret = unsafe { nc::pidfd_send_signal(pidfd, nc::SIGKILL, &mut info, 0) };
    println!("ret: {:?}", ret);
    if let Err(errno) = ret {
        eprintln!("pidfd_send_signal() failed, err: {}", nc::strerror(errno));
    }

    unsafe {
        let ret = nc::close(pidfd);
        assert!(ret.is_ok());
        let ret = nc::close(child_stdout_fd);
        assert!(ret.is_ok());
    }
}