tools: Replace stdin/out with /dev/null on fork

Mirrors the fix from
aa4633b894.

Fixes the hang of a pipeline like `wl-copy hello | cat`.
This commit is contained in:
Ivan Molodetskikh
2022-03-20 11:54:49 +03:00
parent 2d85e0bbac
commit 6ad53edcef
2 changed files with 30 additions and 2 deletions

View File

@@ -7,7 +7,11 @@ use std::{
};
use anyhow::{Context, Error};
use nix::unistd::{fork, ForkResult};
use libc::{STDIN_FILENO, STDOUT_FILENO};
use nix::{
fcntl::OFlag,
unistd::{close, dup2, fork, ForkResult},
};
use wl_clipboard_rs::{
copy::{self, ServeRequests, Source},
@@ -283,6 +287,16 @@ fn main() -> Result<(), Error> {
// SAFETY: We don't spawn any threads, so doing things after forking is safe.
// TODO: is there any way to verify that we don't spawn any threads?
if let ForkResult::Child = unsafe { fork() }.unwrap() {
// Replace STDIN and STDOUT with /dev/null. We won't be using them, and keeping them as
// is hangs a potential pipeline (i.e. wl-copy hello | cat). Also, simply closing the
// file descriptors is a bad idea because then they get reused by subsequent temp file
// opens, which breaks the dup2/close logic during data copying.
if let Ok(dev_null) = nix::fcntl::open("/dev/null", OFlag::O_RDWR, nix::sys::stat::Mode::empty()) {
let _ = dup2(dev_null, STDIN_FILENO);
let _ = dup2(dev_null, STDOUT_FILENO);
let _ = close(dev_null);
}
drop(prepared_copy.serve());
}
}

View File

@@ -1,6 +1,10 @@
use std::{ffi::OsString, os::unix::ffi::OsStringExt};
use nix::unistd::{fork, ForkResult};
use libc::{STDIN_FILENO, STDOUT_FILENO};
use nix::{
fcntl::OFlag,
unistd::{close, dup2, fork, ForkResult},
};
use structopt::{clap::AppSettings, StructOpt};
use wl_clipboard_rs::copy::{self, clear, ClipboardType, MimeType, Seat, ServeRequests, Source};
@@ -148,6 +152,16 @@ fn main() -> Result<(), anyhow::Error> {
// SAFETY: We don't spawn any threads, so doing things after forking is safe.
// TODO: is there any way to verify that we don't spawn any threads?
if let ForkResult::Child = unsafe { fork() }.unwrap() {
// Replace STDIN and STDOUT with /dev/null. We won't be using them, and keeping them as
// is hangs a potential pipeline (i.e. wl-copy hello | cat). Also, simply closing the
// file descriptors is a bad idea because then they get reused by subsequent temp file
// opens, which breaks the dup2/close logic during data copying.
if let Ok(dev_null) = nix::fcntl::open("/dev/null", OFlag::O_RDWR, nix::sys::stat::Mode::empty()) {
let _ = dup2(dev_null, STDIN_FILENO);
let _ = dup2(dev_null, STDOUT_FILENO);
let _ = close(dev_null);
}
drop(prepared_copy.serve());
}
}