Skip to content

Commit

Permalink
Restore default (ignore) Rust SIGPIPE behavior
Browse files Browse the repository at this point in the history
Remove `reset_sigpipe` and other code that handles `SIGPIPE` in any
way, such as ignoring it or forwarding it to the child process.

This restores the default behaviour of the Rust standard library,
which is to always ignore the signal. This behaviour will be inherited
by the child process.

See #12 for context.
  • Loading branch information
unflxw committed Nov 7, 2024
1 parent 43fab5f commit f6beddb
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 23 deletions.
4 changes: 1 addition & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::cli::Cli;
use crate::client::client;
use crate::log::{LogConfig, LogMessage, LogSeverity};
use crate::package::NAME;
use crate::signals::{has_terminating_intent, reset_sigpipe, signal_stream};
use crate::signals::{has_terminating_intent, signal_stream};
use crate::timestamp::SystemTimestamp;

use ::log::{debug, error, trace};
Expand All @@ -38,8 +38,6 @@ use clap::Parser;
use env_logger::Env;

fn main() {
reset_sigpipe();

env_logger::Builder::from_env(Env::default().default_filter_or("info"))
.format(|buf, record| {
let level = record.level().to_string().to_ascii_lowercase();
Expand Down
21 changes: 1 addition & 20 deletions src/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ fn nix_to_tokio(signal: &Signal) -> SignalKind {
Signal::SIGTERM => SignalKind::terminate(),
Signal::SIGHUP => SignalKind::hangup(),
Signal::SIGQUIT => SignalKind::quit(),
Signal::SIGPIPE => SignalKind::pipe(),
Signal::SIGUSR1 => SignalKind::user_defined1(),
Signal::SIGUSR2 => SignalKind::user_defined2(),
Signal::SIGWINCH => SignalKind::window_change(),
Expand All @@ -25,15 +24,14 @@ fn nix_to_tokio(signal: &Signal) -> SignalKind {
// This list only includes signals that can be caught and handled by the
// application. Signals that cannot be caught, such as SIGKILL and SIGSTOP,
// are not included.
const CHILD_FORWARDABLE_SIGNALS: [Signal; 8] = [
const CHILD_FORWARDABLE_SIGNALS: [Signal; 7] = [
Signal::SIGUSR1,
Signal::SIGUSR2,
Signal::SIGWINCH,
Signal::SIGINT,
Signal::SIGTERM,
Signal::SIGHUP,
Signal::SIGQUIT,
Signal::SIGPIPE,
];

// Returns whether a signal returned by a `signal_stream` represents an intent
Expand All @@ -50,7 +48,6 @@ const CHILD_FORWARDABLE_SIGNALS: [Signal; 8] = [
// - `SIGWINCH`, which notifies the process of a terminal resize (and whose default
// behaviour is to be ignored)
// - `SIGHUP`, which is sometimes used to trigger configuration refreshes
// - `SIGPIPE`, which notifies the process of a broken pipe
//
// The objective is to ensure that only signals which were sent with the explicit
// intent to terminate the child process cause this process to terminate.
Expand All @@ -70,19 +67,3 @@ pub fn signal_stream() -> io::Result<impl Stream<Item = Signal>> {

Ok(signals.map(|(signal, _)| signal))
}

// This function resets the SIGPIPE signal to its default behavior.
// It is called at the beginning of the program.
//
// Signal handlers are inherited by child processes, and most software
// expects SIGPIPE to be set to its default behavior. However,
// the Rust standard library sets SIGPIPE to be ignored by default, which
// can cause the child processes to behave differently than expected.
//
// See https://github.com/kurtbuilds/sigpipe (and the discussions linked
// in the README) for more information.
pub fn reset_sigpipe() {
unsafe {
libc::signal(libc::SIGPIPE, libc::SIG_DFL);
}
}

0 comments on commit f6beddb

Please sign in to comment.