-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathsignal_watcher.html
194 lines (151 loc) · 8.58 KB
/
signal_watcher.html
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
<html>
<head><title>Dasynq manual - signal_watcher</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="content">
<h1>signal_watcher, signal_watcher_impl</h1>
<pre>
// Members of dasynq::event_loop<T> instantiation:
class signal_watcher;
template <class Derived> class <a href="#signal_watcher_impl">signal_watcher_impl</a>; // : public signal_watcher;
</pre>
<h2>signal_watcher</h2>
<p><b>Brief</b>: <i class="code-name">signal_watcher</i> is a member type of the <a href="event_loop.html"><i class="code-name">event_loop</i></a>
template class. It represents an event watcher for POSIX signal reception events; a registered
<i class="code-name">signal_watcher</i> will receive callbacks when its associated signal is received. The
<i class="code-name">signal_watcher</i> class should not be subclassed directly; the
<a href="#signal_watcher_impl"><i class="code-name">signal_watcher_impl</i></a> template provides a means for subclassing.</p>
<h2>Members</h2>
<div class="small-indent">
<h3>Types</h3>
<ul>
<li><i class="code-name">event_loop_t</i> — the event loop type that this watcher registers with.</li>
<li><i class="code-name"><a href="#siginfo_p">siginfo_p</a></i> — a receiver type for signal parameters / information. May be
a reference type.</li>
</ul>
<h3>Constructors</h3>
<ul>
<li><i class="code-name">signal_watcher()</i> — default constructor.</li>
</ul>
<h3>Functions</h3>
<ul>
<li>(#1) <i class="code-name">void add_watch(event_loop_t &eloop, int signo, int prio = DEFAULT_PRIORITY)</i>
<br>— register a watcher with an event loop. <i class="code-name">signo</i> specifies the signal
to watch. May throw <i class="code-name">std::bad_alloc</i> or <i class="code-name">std::system_error</i>.</li>
<li>(#2) <i class="code-name">template <typename T>
<br>static signal_watcher<event_loop_t> *add_watch(event_loop_t &eloop, int signo, T watch_hndlr)</i>
<br>— add a dynamically-allocated watch with the specified callback. The watch is automatically
deleted when removed. See <a href="#add_watch_2">details</a> below.</li>
<li><i class="code-name">void deregister(event_loop_t &eloop) noexcept</i>
<br>— request removal from the event loop.</li>
<li><i class="code-name">virtual void watch_removed() noexcept</i> — called when the watcher has been
removed from the event loop.</li>
</ul>
<h2>Details and Usage</h2>
<p><span class="note"><i>Note:</i> also see the <a href="event_loop.html#watcher-constraints">watcher constraints</a> section.</span></p>
<p>A <i class="code-name">signal_watcher</i> implementation receives notification of delivery of the chosen
POSIX signal. An application should establish a separate <i class="code-name">signal_watcher</i> for each
signal it wishes to monitor.</p>
<p>A signal should be (and should remain) blocked in all threads prior to registration of a watcher for the
signal (this can be achieved using <i class="code-name">sigprocmask</i> or
<i class="code-name">pthread_sigmask</i>). Threads inherit their signal mask from their creator; threads
created by libraries should always have all signals blocked, but there may be badly-behaved libraries which
fail to adhere to this rule. Therefore, it is recommended to block required signals early in the application
lifetime (before initialising other libraries) if possible.</p>
<p>Note that signals are consumed before the watcher callback is called. A watched signal should not be
consumed by any means any other polling the event loop (i.e. should not be unblocked, and should not
be consumed using <i class="code-name">sigwaitinfo</i> or similar functions).
<br><span class="note"><i>Note:</i> Dasynq in general does its best to work correctly when signals are
consumed outside the event loop. However on some systems, especially those lacking realtime signal
extensions (such as MacOS and OpenBSD), an unavoidable race condition occurs when a watched signal is
consumed in a different thread while the loop is being polled, which may lead to a deadlock).</span>
</p>
<h3>Subclassing signal_watcher</h3>
<p>To specify callback behaviour, <i class="code-name">signal_watcher</i> can be subclassed — however, it should
not be directly subclassed; instead, use the <i class="code-name">signal_watcher_impl</i> implementation wrapper
template.</p>
<h2 id="add_watch_2">add_watch (#2)</h2>
<pre>
// member of dasynq::event_loop<T>::signal_watcher
template <typename T>
static signal_watcher<event_loop_t> *add_watch(event_loop_t &eloop, int signo, T watch_hndlr);
</pre>
<p>This variant of the <i class="code-name">add_watch</i> function can be used to create and register a
dynamically-allocated <i class="code-name">signal_watcher</i>. The first two parameters are the same as for
<i class="code-name">add_watch</i>(#1). The <i class="code-name">watch_hndlr</i> parameter is a function
or lambda of the form:</p>
<pre>
[](event_loop_t &eloop, int signo, <a href="#siginfo_p">siginfo_p</a> siginfo) -> rearm { ... }
</pre>
<p>It acts as the callback function for the generated watcher. The watcher will delete itself when it is
removed from the event loop.</p>
<p>This function can throw <i class="code-name">std::system_error</i> or
<i class="code-name">std::bad_alloc</i> on failure.</p>
<hr>
<h2 id="signal_watcher_impl">signal_watcher_impl</h2>
<p><b>Brief</b>: The <i class="code-name">signal_watcher_impl</i> provides a basis for implementing
<i class="code-name">signal_watcher</i>, using the "curiously recurring template pattern". Instead of
subclassing <i class="code-name">signal_watcher</i> directly, subclass an instantiation of
<i class="code-name">signal_watcher_impl</i> with the template parameter specified as the subclass itself.
For example:</p>
<pre>
class my_watcher : public event_loop_t::signal_watcher_impl<my_watcher>
{
// ...
}
</pre>
<h2>Details and Usage</h2>
<p>The callback function must be provided in the subclass and named <i class="code-name">received</i>, with
a signature compatible with the following:</p>
<pre>
rearm received(event_loop_t & loop, int signo, <a href="#siginfo_p">siginfo_p</a> siginfo) noexcept;
</pre>
<p>The <i class="code-name">received</i> function must be public, but need not be virtual. It will be called
with the following parameters:</p>
<ul>
<li><i class="code-name">loop</i> — a reference to the event loop.</li>
<li><i class="code-name">signo</i> — the signal number.</li>
<li><i class="code-name">siginfo</i> — the signal data associated with the delivered signal instance.</li>
</ul>
<p>The return value specifies the <a href="dasynq-namespace.html"><i class="code-name">rearm</i></a> action.</p>
<p>A <i class="code-name">signal_watcher_impl</i> instantiation has no public or protected members, other than
those inherited from <i class="code-name">signal_watcher</i>, which it publicly derives from.</p>
<hr>
<h2 id="siginfo_p">siginfo_p - dasynq::event_loop<T>::signal_watcher::siginfo_p</h2>
<pre>
class siginfo_p // may be a typedef
{
// mandatory functions:
int get_signo(); // si_signo : signal number
int get_sicode(); // si_code
pid_t get_sipid(); // si_pid
uid_t get_siuid(); // si_uid
void * get_siaddr(); // si_addr
int get_sistatus(); // si_status
int get_sival_int(); // si_value.sival_int
void * get_sival_ptr(); // si_value.sival_ptr
// optional functions as per POSIX:
int get_sierrno(); // si_errno
int get_siband(); // si_band (not available on OpenBSD)
// Linux-only functions:
int get_sifd(); // si_fd
int get_sitimerid(); // si_timerid
int get_sioverrun(); // si_overrun
int get_sitrapno(); // si_trapno
clock_t get_siutime(); // si_utime
clock_t get_sistime(); // si_stime
short get_siaddr_lsb(); // si_addr_lsb
// Other functions may be present.
};
</pre>
<h2>Details</h2>
<p>The <i class="code-name">siginfo_p</i> type is used to pass signal data as a function parameter. It may
be a reference type. It is intended to be (or be a reference to) a wrapper around the POSIX <i class="code-name">siginfo_t</i>
type; various functions are available to retrieve the standard <i class="code-name">si_</i>-prefixed data
members.</p>
<p>Because different platforms tend to expose different members, this type may define different functions
on different platforms. However, the "mandatory" functions should be available on all platforms, and other
functions which provide access to POSIX-specified data members should be available if the corresponding
POSIX functionality is present.</p>
</div></body></html>