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
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
99
100
101
102
// Copyright (C) 2018,2021 Daniel Mueller <deso@posteo.net>
// SPDX-License-Identifier: GPL-3.0-or-later
//! Infrastructure for intercepting and handling SIGWINCH signals.
//!
//! The purpose of this module is to install a signal handler for
//! SIGWINCH, intercept them, and send an event indicating that such a
//! signal was received through a supplied `std::sync::mpsc::Sender`
//! part of a `std::sync::mpsc::channel`.
//!
//! Signal handling is icky and a signal handler is a particularly
//! disgusting context to run in. It is inherently unsafe because there
//! are severe limitations as to what functions may be invoked. More
//! specifically, we must not invoke anything that grabs a lock in order
//! to guarantee dead lock freedom (a signal handler may interrupt and
//! stop the running thread at an arbitrary time, including when it has
//! acquired a lock; given that the thread will not be running we would
//! deadlock if we were to attempt to acquire the same lock).
//!
//! We would ideally want to directly send an event through a channel
//! from a signal handler, but it is left undefined whether the channel
//! primitive may use locks. To be safe, we instead have a thread
//! waiting on a pipe and just send a byte through this pipe to cause a
//! wake up. The thread will subsequently write to the channel as
//! desired -- from a context that is safe.
//!
//! Note that with signalfd(2) another primitive exist that takes care
//! of part of the work. However, it was not chosen for two reasons:
//! 1) It is Linux specific.
//! 2) It requires us to mask the signal we want to receive with it on
//! all threads. That means we need to somehow run disabling logic in
//! all threads we would want to create, ever.
use PartialOrd;
use Error;
use ErrorKind;
use Result;
use Sender;
use thread;
use c_int;
use c_void;
use pipe;
use read;
use signal;
use size_t;
use write;
use SIGWINCH;
use SIG_ERR;
use crateEvent;
/// The file descriptor for a write end of a pipe used for signaling resize events.
static mut WRITE_FD: c_int = 0;
/// Check the return value of a system call.
/// A signal handler for SIGWINCH that sends a byte through `WRITE_FD` to wake up a thread.
extern "C"
/// Register a signal handler for `SIGWINCH` and send a `Event::Resize` object upon interception.