async-unix.h (15007B)
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors 2 // Licensed under the MIT License: 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 22 #pragma once 23 24 #if _WIN32 25 #error "This file is Unix-specific. On Windows, include async-win32.h instead." 26 #endif 27 28 #include "async.h" 29 #include "timer.h" 30 #include "vector.h" 31 #include "io.h" 32 #include <signal.h> 33 34 KJ_BEGIN_HEADER 35 36 #if __linux__ && !__BIONIC__ && !defined(KJ_USE_EPOLL) 37 // Default to epoll on Linux, except on Bionic (Android) which doesn't have signalfd.h. 38 #define KJ_USE_EPOLL 1 39 #endif 40 41 #if __CYGWIN__ && !defined(KJ_USE_PIPE_FOR_WAKEUP) 42 // Cygwin has serious issues with the intersection of signals and threads, reported here: 43 // https://cygwin.com/ml/cygwin/2019-07/msg00052.html 44 // On Cygwin, therefore, we do not use signals to wake threads. Instead, each thread allocates a 45 // pipe, and we write a byte to the pipe to wake the thread... ick. 46 #define KJ_USE_PIPE_FOR_WAKEUP 1 47 #endif 48 49 namespace kj { 50 51 class UnixEventPort: public EventPort { 52 // An EventPort implementation which can wait for events on file descriptors as well as signals. 53 // This API only makes sense on Unix. 54 // 55 // The implementation uses `poll()` or possibly a platform-specific API (e.g. epoll, kqueue). 56 // To also wait on signals without race conditions, the implementation may block signals until 57 // just before `poll()` while using a signal handler which `siglongjmp()`s back to just before 58 // the signal was unblocked, or it may use a nicer platform-specific API like signalfd. 59 // 60 // The implementation reserves a signal for internal use. By default, it uses SIGUSR1. If you 61 // need to use SIGUSR1 for something else, you must offer a different signal by calling 62 // setReservedSignal() at startup. 63 // 64 // WARNING: A UnixEventPort can only be used in the thread and process that created it. In 65 // particular, note that after a fork(), a UnixEventPort created in the parent process will 66 // not work correctly in the child, even if the parent ceases to use its copy. In particular 67 // note that this means that server processes which daemonize themselves at startup must wait 68 // until after daemonization to create a UnixEventPort. 69 70 public: 71 UnixEventPort(); 72 ~UnixEventPort() noexcept(false); 73 74 class FdObserver; 75 // Class that watches an fd for readability or writability. See definition below. 76 77 Promise<siginfo_t> onSignal(int signum); 78 // When the given signal is delivered to this thread, return the corresponding siginfo_t. 79 // The signal must have been captured using `captureSignal()`. 80 // 81 // If `onSignal()` has not been called, the signal will remain blocked in this thread. 82 // Therefore, a signal which arrives before `onSignal()` was called will not be "missed" -- the 83 // next call to 'onSignal()' will receive it. Also, you can control which thread receives a 84 // process-wide signal by only calling `onSignal()` on that thread's event loop. 85 // 86 // The result of waiting on the same signal twice at once is undefined. 87 88 static void captureSignal(int signum); 89 // Arranges for the given signal to be captured and handled via UnixEventPort, so that you may 90 // then pass it to `onSignal()`. This method is static because it registers a signal handler 91 // which applies process-wide. If any other threads exist in the process when `captureSignal()` 92 // is called, you *must* set the signal mask in those threads to block this signal, otherwise 93 // terrible things will happen if the signal happens to be delivered to those threads. If at 94 // all possible, call `captureSignal()` *before* creating threads, so that threads you create in 95 // the future will inherit the proper signal mask. 96 // 97 // To un-capture a signal, simply install a different signal handler and then un-block it from 98 // the signal mask. 99 100 static void setReservedSignal(int signum); 101 // Sets the signal number which `UnixEventPort` reserves for internal use. If your application 102 // needs to use SIGUSR1, call this at startup (before any calls to `captureSignal()` and before 103 // constructing an `UnixEventPort`) to offer a different signal. 104 105 Timer& getTimer() { return timerImpl; } 106 107 Promise<int> onChildExit(Maybe<pid_t>& pid); 108 // When the given child process exits, resolves to its wait status, as returned by wait(2). You 109 // will need to use the WIFEXITED() etc. macros to interpret the status code. 110 // 111 // You must call onChildExit() immediately after the child is created, before returning to the 112 // event loop. Otherwise, you may miss the child exit event. 113 // 114 // `pid` is a reference to a Maybe<pid_t> which must be non-null at the time of the call. When 115 // wait() is invoked (and indicates this pid has finished), `pid` will be nulled out. This is 116 // necessary to avoid a race condition: as soon as the child has been wait()ed, the PID table 117 // entry is freed and can then be reused. So, if you ever want safely to call `kill()` on the 118 // PID, it's necessary to know whether it has been wait()ed already. Since the promise's 119 // .then() continuation may not run immediately, we need a more precise way, hence we null out 120 // the Maybe. 121 // 122 // You must call `kj::UnixEventPort::captureChildExit()` early in your program if you want to use 123 // `onChildExit()`. 124 // 125 // WARNING: Only one UnixEventPort per process is allowed to use onChildExit(). This is because 126 // child exit is signaled to the process via SIGCHLD, and Unix does not allow the program to 127 // control which thread receives the signal. (We may fix this in the future by automatically 128 // coordinating between threads when multiple threads are expecting child exits.) 129 // WARNING 2: If any UnixEventPort in the process is currently waiting for onChildExit(), then 130 // *only* that port's thread can safely wait on child processes, even synchronously. This is 131 // because the thread which used onChildExit() uses wait() to reap children, without specifying 132 // which child, and therefore it may inadvertently reap children created by other threads. 133 134 static void captureChildExit(); 135 // Arranges for child process exit to be captured and handled via UnixEventPort, so that you may 136 // call `onChildExit()`. Much like `captureSignal()`, this static method must be called early on 137 // in program startup. 138 // 139 // This method may capture the `SIGCHLD` signal. You must not use `captureSignal(SIGCHLD)` nor 140 // `onSignal(SIGCHLD)` in your own code if you use `captureChildExit()`. 141 142 // implements EventPort ------------------------------------------------------ 143 bool wait() override; 144 bool poll() override; 145 void wake() const override; 146 147 private: 148 class SignalPromiseAdapter; 149 class ChildExitPromiseAdapter; 150 151 const MonotonicClock& clock; 152 TimerImpl timerImpl; 153 154 SignalPromiseAdapter* signalHead = nullptr; 155 SignalPromiseAdapter** signalTail = &signalHead; 156 157 void gotSignal(const siginfo_t& siginfo); 158 159 friend class TimerPromiseAdapter; 160 161 #if KJ_USE_EPOLL 162 AutoCloseFd epollFd; 163 AutoCloseFd signalFd; 164 AutoCloseFd eventFd; // Used for cross-thread wakeups. 165 166 sigset_t signalFdSigset; 167 // Signal mask as currently set on the signalFd. Tracked so we can detect whether or not it 168 // needs updating. 169 170 bool doEpollWait(int timeout); 171 172 #else 173 class PollContext; 174 175 FdObserver* observersHead = nullptr; 176 FdObserver** observersTail = &observersHead; 177 178 #if KJ_USE_PIPE_FOR_WAKEUP 179 AutoCloseFd wakePipeIn; 180 AutoCloseFd wakePipeOut; 181 #else 182 unsigned long long threadId; // actually pthread_t 183 #endif 184 #endif 185 186 struct ChildSet; 187 Maybe<Own<ChildSet>> childSet; 188 }; 189 190 class UnixEventPort::FdObserver { 191 // Object which watches a file descriptor to determine when it is readable or writable. 192 // 193 // For listen sockets, "readable" means that there is a connection to accept(). For everything 194 // else, it means that read() (or recv()) will return data. 195 // 196 // The presence of out-of-band data should NOT fire this event. However, the event may 197 // occasionally fire spuriously (when there is actually no data to read), and one thing that can 198 // cause such spurious events is the arrival of OOB data on certain platforms whose event 199 // interfaces fail to distinguish between regular and OOB data (e.g. Mac OSX). 200 // 201 // WARNING: The exact behavior of this class differs across systems, since event interfaces 202 // vary wildly. Be sure to read the documentation carefully and avoid depending on unspecified 203 // behavior. If at all possible, use the higher-level AsyncInputStream interface instead. 204 205 public: 206 enum Flags { 207 OBSERVE_READ = 1, 208 OBSERVE_WRITE = 2, 209 OBSERVE_URGENT = 4, 210 OBSERVE_READ_WRITE = OBSERVE_READ | OBSERVE_WRITE 211 }; 212 213 FdObserver(UnixEventPort& eventPort, int fd, uint flags); 214 // Begin watching the given file descriptor for readability. Only one ReadObserver may exist 215 // for a given file descriptor at a time. 216 217 ~FdObserver() noexcept(false); 218 219 KJ_DISALLOW_COPY(FdObserver); 220 221 Promise<void> whenBecomesReadable(); 222 // Resolves the next time the file descriptor transitions from having no data to read to having 223 // some data to read. 224 // 225 // KJ uses "edge-triggered" event notification whenever possible. As a result, it is an error 226 // to call this method when there is already data in the read buffer which has been there since 227 // prior to the last turn of the event loop or prior to creation FdWatcher. In this case, it is 228 // unspecified whether the promise will ever resolve -- it depends on the underlying event 229 // mechanism being used. 230 // 231 // In order to avoid this problem, make sure that you only call `whenBecomesReadable()` 232 // only at times when you know the buffer is empty. You know this for sure when one of the 233 // following happens: 234 // * read() or recv() fails with EAGAIN or EWOULDBLOCK. (You MUST have non-blocking mode 235 // enabled on the fd!) 236 // * The file descriptor is a regular byte-oriented object (like a socket or pipe), 237 // read() or recv() returns fewer than the number of bytes requested, and `atEndHint()` 238 // returns false. This can only happen if the buffer is empty but EOF is not reached. (Note, 239 // though, that for record-oriented file descriptors like Linux's inotify interface, this 240 // rule does not hold, because it could simply be that the next record did not fit into the 241 // space available.) 242 // 243 // It is an error to call `whenBecomesReadable()` again when the promise returned previously 244 // has not yet resolved. If you do this, the previous promise may throw an exception. 245 246 inline Maybe<bool> atEndHint() { return atEnd; } 247 // Returns true if the event system has indicated that EOF has been received. There may still 248 // be data in the read buffer, but once that is gone, there's nothing left. 249 // 250 // Returns false if the event system has indicated that EOF had NOT been received as of the 251 // last turn of the event loop. 252 // 253 // Returns nullptr if the event system does not know whether EOF has been reached. In this 254 // case, the only way to know for sure is to call read() or recv() and check if it returns 255 // zero. 256 // 257 // This hint may be useful as an optimization to avoid an unnecessary system call. 258 259 Promise<void> whenBecomesWritable(); 260 // Resolves the next time the file descriptor transitions from having no space available in the 261 // write buffer to having some space available. 262 // 263 // KJ uses "edge-triggered" event notification whenever possible. As a result, it is an error 264 // to call this method when there is already space in the write buffer which has been there 265 // since prior to the last turn of the event loop or prior to creation FdWatcher. In this case, 266 // it is unspecified whether the promise will ever resolve -- it depends on the underlying 267 // event mechanism being used. 268 // 269 // In order to avoid this problem, make sure that you only call `whenBecomesWritable()` 270 // only at times when you know the buffer is full. You know this for sure when one of the 271 // following happens: 272 // * write() or send() fails with EAGAIN or EWOULDBLOCK. (You MUST have non-blocking mode 273 // enabled on the fd!) 274 // * write() or send() succeeds but accepts fewer than the number of bytes provided. This can 275 // only happen if the buffer is full. 276 // 277 // It is an error to call `whenBecomesWritable()` again when the promise returned previously 278 // has not yet resolved. If you do this, the previous promise may throw an exception. 279 280 Promise<void> whenUrgentDataAvailable(); 281 // Resolves the next time the file descriptor's read buffer contains "urgent" data. 282 // 283 // The conditions for availability of urgent data are specific to the file descriptor's 284 // underlying implementation. 285 // 286 // It is an error to call `whenUrgentDataAvailable()` again when the promise returned previously 287 // has not yet resolved. If you do this, the previous promise may throw an exception. 288 // 289 // WARNING: This has some known weird behavior on macOS. See 290 // https://github.com/sandstorm-io/capnproto/issues/374. 291 292 Promise<void> whenWriteDisconnected(); 293 // Resolves when poll() on the file descriptor reports POLLHUP or POLLERR. 294 295 private: 296 UnixEventPort& eventPort; 297 int fd; 298 uint flags; 299 300 kj::Maybe<Own<PromiseFulfiller<void>>> readFulfiller; 301 kj::Maybe<Own<PromiseFulfiller<void>>> writeFulfiller; 302 kj::Maybe<Own<PromiseFulfiller<void>>> urgentFulfiller; 303 kj::Maybe<Own<PromiseFulfiller<void>>> hupFulfiller; 304 // Replaced each time `whenBecomesReadable()` or `whenBecomesWritable()` is called. Reverted to 305 // null every time an event is fired. 306 307 Maybe<bool> atEnd; 308 309 void fire(short events); 310 311 #if !KJ_USE_EPOLL 312 FdObserver* next; 313 FdObserver** prev; 314 // Linked list of observers which currently have a non-null readFulfiller or writeFulfiller. 315 // If `prev` is null then the observer is not currently in the list. 316 317 short getEventMask(); 318 #endif 319 320 friend class UnixEventPort; 321 }; 322 323 } // namespace kj 324 325 KJ_END_HEADER