safewrappers.html (4003B)
1 <html> 2 <head> 3 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 5 <meta http-equiv="Content-Language" content="en" /> 6 <title>skalibs: safe wrappers</title> 7 <meta name="Description" content="skalibs: safe wrappers" /> 8 <meta name="Keywords" content="skalibs c unix safe wrappers safewrappers library libstddjb" /> 9 <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> --> 10 </head> 11 <body> 12 13 <p> 14 <a href="index.html">libstddjb</a><br /> 15 <a href="../libskarnet.html">libskarnet</a><br /> 16 <a href="../index.html">skalibs</a><br /> 17 <a href="//skarnet.org/software/">Software</a><br /> 18 <a href="//skarnet.org/">skarnet.org</a> 19 </p> 20 21 <h1> Safe wrappers </h1> 22 23 <p> 24 Lots of functions in <tt>libstddjb</tt>, declared for instance in 25 <a href="allreadwrite.html">allreadwrite.h</a> or 26 <a href="djbunix.html">djbunix.h</a>, are just "safe wrappers" 27 around corresponding system functions. For instance, 28 <tt>fd_read()</tt> is a safe wrapper around the system <tt>read()</tt> 29 function. 30 </p> 31 32 <h2> The problem </h2> 33 34 <p> 35 Quite a lot of system calls are defined by 36 <a href="https://www.opengroup.org/onlinepubs/9699919799/nfindex.html">The 37 Open Group Base Specifications</a> as interruptible: when the process is in 38 the middle of such a system call and receives a signal that it does not 39 ignore, the system call immediately returns -1 EINTR (after the signal 40 handler, if any, has been executed). 41 </p> 42 43 <p> 44 Most of the time, this is not an issue: unignored signals usually kill 45 the process anyway. Or stop it - and when it resumes, system calls are 46 simply restarted, not interrupted. EINTR can only happen when a signal 47 handler has been installed, and a signal is actually caught by the 48 signal handler during an interruptible system call. And to avoid EINTR, 49 users can use the SA_RESTART flag when installing the signal handler with 50 <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html">sigaction()</a>. 51 </p> 52 53 <p> 54 However, there is a common case where using SA_RESTART is a bad idea: 55 when writing an asynchronous event loop. 56 </p> 57 58 <p> 59 An asynchronous event loop is organized around a 60 <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html">select()</a> or 61 <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html">poll()</a> 62 system call that is the only blocking operation in the whole loop. That call takes a 63 timeout as an argument. If a signal handler is installed with SA_RESTART and a 64 signal arrives in the middle of the select/poll call - which happens often 65 since it is blocking - then the select/poll is restarted with the same arguments, 66 including the timeout. This is not good: time has elapsed, the timeout should be 67 recomputed. Some versions of select update the values in the struct timeval even 68 when select() is interrupted, but it is not portable, and not applicable to poll(). 69 So it is necessary, in this case, to have select/poll return -1 EINTR when a 70 signal is caught. And that means SA_RESTART should not be used. 71 </p> 72 73 <p> 74 Which also means that other system calls performed when the signal handler has 75 been installed, for instance in the body of the loop, will <em>not</em> be 76 protected, and can return -1 EINTR if a signal is caught at the wrong time. 77 </p> 78 79 <h2> The solution </h2> 80 81 <p> 82 So, in order to be perfectly reliable, when a program has caught a signal 83 without SA_RESTART and makes an interruptible system call, it must check whether 84 the return value is -1 EINTR, and restart the system call if it is the case. 85 This is annoying to write; so, skalibs provides small wrappers around 86 interruptible system calls, so that programmers can just call those safe wrappers 87 and never bother with this again. 88 </p> 89 90 <p> 91 The performance loss from having a wrapper layer is totally negligible 92 compared to the cost of using a system call in the first place. 93 </p> 94 95 </body> 96 </html>