1/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to 5 * deal in the Software without restriction, including without limitation the 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 * sell copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 * IN THE SOFTWARE. 20 */ 21 22#include "uv.h" 23#include "internal.h" 24 25#include <unistd.h> 26#include <assert.h> 27#include <errno.h> 28 29 30static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { 31 uv_poll_t* handle; 32 int pevents; 33 34 handle = container_of(w, uv_poll_t, io_watcher); 35 36 /* 37 * As documented in the kernel source fs/kernfs/file.c #780 38 * poll will return POLLERR|POLLPRI in case of sysfs 39 * polling. This does not happen in case of out-of-band 40 * TCP messages. 41 * 42 * The above is the case on (at least) FreeBSD and Linux. 43 * 44 * So to properly determine a POLLPRI or a POLLERR we need 45 * to check for both. 46 */ 47 if ((events & POLLERR) && !(events & UV__POLLPRI)) { 48 uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI); 49 uv__handle_stop(handle); 50 handle->poll_cb(handle, UV_EBADF, 0); 51 return; 52 } 53 54 pevents = 0; 55 if (events & POLLIN) 56 pevents |= UV_READABLE; 57 if (events & UV__POLLPRI) 58 pevents |= UV_PRIORITIZED; 59 if (events & POLLOUT) 60 pevents |= UV_WRITABLE; 61 if (events & UV__POLLRDHUP) 62 pevents |= UV_DISCONNECT; 63 64 handle->poll_cb(handle, 0, pevents); 65} 66 67 68int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { 69 int err; 70 71 if (uv__fd_exists(loop, fd)) 72 return UV_EEXIST; 73 74 err = uv__io_check_fd(loop, fd); 75 if (err) 76 return err; 77 78 /* If ioctl(FIONBIO) reports ENOTTY, try fcntl(F_GETFL) + fcntl(F_SETFL). 79 * Workaround for e.g. kqueue fds not supporting ioctls. 80 */ 81 err = uv__nonblock(fd, 1); 82#if UV__NONBLOCK_IS_IOCTL 83 if (err == UV_ENOTTY) 84 err = uv__nonblock_fcntl(fd, 1); 85#endif 86 87 if (err) 88 return err; 89 90 uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL); 91 uv__io_init(&handle->io_watcher, uv__poll_io, fd); 92 handle->poll_cb = NULL; 93 return 0; 94} 95 96 97int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, 98 uv_os_sock_t socket) { 99 return uv_poll_init(loop, handle, socket); 100} 101 102 103static void uv__poll_stop(uv_poll_t* handle) { 104 uv__io_stop(handle->loop, 105 &handle->io_watcher, 106 POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI); 107 uv__handle_stop(handle); 108 uv__platform_invalidate_fd(handle->loop, handle->io_watcher.fd); 109} 110 111 112int uv_poll_stop(uv_poll_t* handle) { 113 assert(!uv__is_closing(handle)); 114 uv__poll_stop(handle); 115 return 0; 116} 117 118 119int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) { 120 uv__io_t** watchers; 121 uv__io_t* w; 122 int events; 123 124 assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT | 125 UV_PRIORITIZED)) == 0); 126 assert(!uv__is_closing(handle)); 127 128 watchers = handle->loop->watchers; 129 w = &handle->io_watcher; 130 131 if (uv__fd_exists(handle->loop, w->fd)) 132 if (watchers[w->fd] != w) 133 return UV_EEXIST; 134 135 uv__poll_stop(handle); 136 137 if (pevents == 0) 138 return 0; 139 140 events = 0; 141 if (pevents & UV_READABLE) 142 events |= POLLIN; 143 if (pevents & UV_PRIORITIZED) 144 events |= UV__POLLPRI; 145 if (pevents & UV_WRITABLE) 146 events |= POLLOUT; 147 if (pevents & UV_DISCONNECT) 148 events |= UV__POLLRDHUP; 149 150 uv__io_start(handle->loop, &handle->io_watcher, events); 151 uv__handle_start(handle); 152 handle->poll_cb = poll_cb; 153 154 return 0; 155} 156 157 158void uv__poll_close(uv_poll_t* handle) { 159 uv__poll_stop(handle); 160} 161