summaryrefslogtreecommitdiff
path: root/doc/libstddjb/safewrappers.html
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2014-12-08 23:26:20 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2014-12-08 23:26:20 +0000
commite4348f29c1e0bca44ea43b35cb18ca9b58dbe16b (patch)
treefc96f4076d79a033851b8ed5b30014b98ac8d7a7 /doc/libstddjb/safewrappers.html
parent51e3113781aa42e38396d352ff77ea1f1bd29643 (diff)
downloadskalibs-e4348f29c1e0bca44ea43b35cb18ca9b58dbe16b.tar.xz
Documentation update: safe wrappers
Diffstat (limited to 'doc/libstddjb/safewrappers.html')
-rw-r--r--doc/libstddjb/safewrappers.html66
1 files changed, 35 insertions, 31 deletions
diff --git a/doc/libstddjb/safewrappers.html b/doc/libstddjb/safewrappers.html
index 6d889d6..37d2425 100644
--- a/doc/libstddjb/safewrappers.html
+++ b/doc/libstddjb/safewrappers.html
@@ -40,51 +40,55 @@ handler, if any, has been executed).
</p>
<p>
- This means that the intended execution of the process is at the mercy
-of a stray signal. If a signal happens at the wrong time, a system call
-fails when it could have succeeded. This is not acceptable.
+ Most of the time, this is not an issue: unignored signals usually kill
+the process anyway. Or stop it - and when it resumes, system calls are
+simply restarted, not interrupted. EINTR can only happen when a signal
+handler has been installed, and a signal is actually caught by the
+signal handler during an interruptible system call. And to avoid EINTR,
+users can use the SA_RESTART flag when installing the signal handler with
+<a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html">sigaction()</a>.
</p>
-<h2> The solution </h2>
+<p>
+ However, there is a common case where using SA_RESTART is a bad idea:
+when writing an asynchronous event loop.
+</p>
<p>
- So, in order to be perfectly reliable, when a program makes an interruptible
-system call, it <em>must</em> check whether the return value is -1 EINTR,
-and restart the system call if it is the case. This is annoying to write;
-so, <tt>libstddjb</tt> provides small wrappers around interruptible system
-calls, so that programmers can just call those <em>safe wrappers</em> and
-never bother with this again.
+ An asynchronous event loop is organized around a
+<a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html">select()</a> or
+<a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html">poll()</a>
+system call that is the only blocking operation in the whole loop. That call takes a
+timeout as an argument. If a signal handler is installed with SA_RESTART and a
+signal arrives in the middle of the select/poll call - which happens often
+since it is blocking - then the select/poll is restarted with the same arguments,
+including the timeout. This is not good: time has elapsed, the timeout should be
+recomputed. Some versions of select update the values in the struct timeval even
+when select() is interrupted, but it is not portable, and not applicable to poll().
+So it is necessary, in this case, to have select/poll return -1 EINTR when a
+signal is caught. And that means SA_RESTART should not be used.
</p>
<p>
- The performance loss from having a wrapper layer is totally negligible
-compared to the cost of using a system call in the first place.
+ Which means that other system calls performed when the signal handler has
+been installed, for instance in the body of the loop, will <em>not</em> be
+protected, and can return -1 EINTR if a signal is caught at the wrong time.
</p>
-<h2> But isn't it what the SA_RESTART flag is meant to address? </h2>
+<h2> The solution </h2>
<p>
- Yes, it is. Unfortunately, SA_RESTART only protects interruptible
-system calls from signals you actually have control over, and set a
-handler for with
-<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/sigaction.html">sigaction()</a>.
-This is not enough. You cannot decide that <em>every</em> signal sent
-to your process should have SA_RESTART behaviour; and the Single Unix
-specification says nothing about signals you do not control. For instance,
-you cannot trap SIGSTOP; SIGSTOP does not kill your process, which
-should resume flawlessly at the next SIGCONT; and according to the
-specification, it is valid for SIGSTOP and SIGCONT to <em>not</em>
-have SA_RESTART behaviour. So if you get a SIGSTOP while performing
-an interruptible system call, that system call may return -1 EINTR,
-this is not an OS bug, and there's nothing you can do about it with
-<tt>sigaction()</tt>.
+ So, in order to be perfectly reliable, when a program has caught a signal
+without SA_RESTART and makes an interruptible system call, it must check whether
+the return value is -1 EINTR, and restart the system call if it is the case.
+This is annoying to write; so, skalibs provides small wrappers around
+interruptible system calls, so that programmers can just call those safe wrappers
+and never bother with this again.
</p>
<p>
- SA_RESTART is only a partial solution: in other words, it doesn't work.
-Until the Single Unix specification explicitly states that untrapped
-non-lethal signals MUST have SA_RESTART behaviour by default, you
-<em>need</em> safe wrappers to protect interruptible system calls.
+ The performance loss from having a wrapper layer is totally negligible
+compared to the cost of using a system call in the first place.
</p>
</body>