1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
//! Scoped `SIGPIPE` suppression for daemon socket I/O.
//!
//! `main::reset_sigpipe` puts `SIGPIPE` back to `SIG_DFL` process-wide, because a
//! one-shot CLI is expected to die quietly when its stdout consumer goes away:
//! `keyhog scan --format json | head -1` must exit like every other Unix filter
//! instead of printing a `BrokenPipe` error and a nonzero code. That is the right
//! disposition for the report writer and the wrong one for a socket.
//!
//! A daemon peer disappearing is ordinary: the operator hits Ctrl-C, a client
//! request times out, a pre-commit hook is killed. With `SIG_DFL` the very next
//! `write(2)` to that socket kills the writing process outright, so the CLI dies
//! by signal 141 instead of reporting which daemon went away. The server side
//! fixes this permanently (see `server::ignore_sigpipe_while_serving`); a client
//! cannot, because it still owns the piped-stdout contract above.
//!
//! So clients suppress `SIGPIPE` only while a daemon connection is open. Report
//! writing happens after the connection is dropped, which keeps the piped-stdout
//! behaviour intact. The guard is reference counted, so overlapping connections
//! restore the default exactly once.
use ;
static ACTIVE_GUARDS: AtomicUsize = new;
/// Suppresses `SIGPIPE` for as long as it is alive. Held by every daemon
/// connection object, so a peer that vanishes mid-write surfaces `EPIPE` to the
/// error path instead of killing the process.
pub ;