kqueue.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
  2. * Permission is hereby granted, free of charge, to any person obtaining a copy
  3. * of this software and associated documentation files (the "Software"), to
  4. * deal in the Software without restriction, including without limitation the
  5. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  6. * sell copies of the Software, and to permit persons to whom the Software is
  7. * furnished to do so, subject to the following conditions:
  8. *
  9. * The above copyright notice and this permission notice shall be included in
  10. * all copies or substantial portions of the Software.
  11. *
  12. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  17. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  18. * IN THE SOFTWARE.
  19. */
  20. #include "uv.h"
  21. #include "internal.h"
  22. #include <assert.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <errno.h>
  26. #include <sys/sysctl.h>
  27. #include <sys/types.h>
  28. #include <sys/event.h>
  29. #include <sys/time.h>
  30. #include <unistd.h>
  31. #include <fcntl.h>
  32. #include <time.h>
  33. /*
  34. * Required on
  35. * - Until at least FreeBSD 11.0
  36. * - Older versions of Mac OS X
  37. *
  38. * http://www.boost.org/doc/libs/1_61_0/boost/asio/detail/kqueue_reactor.hpp
  39. */
  40. #ifndef EV_OOBAND
  41. #define EV_OOBAND EV_FLAG1
  42. #endif
  43. static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags);
  44. int uv__kqueue_init(uv_loop_t* loop) {
  45. loop->backend_fd = kqueue();
  46. if (loop->backend_fd == -1)
  47. return UV__ERR(errno);
  48. uv__cloexec(loop->backend_fd, 1);
  49. return 0;
  50. }
  51. #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
  52. static int uv__has_forked_with_cfrunloop;
  53. #endif
  54. int uv__io_fork(uv_loop_t* loop) {
  55. int err;
  56. loop->backend_fd = -1;
  57. err = uv__kqueue_init(loop);
  58. if (err)
  59. return err;
  60. #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
  61. if (loop->cf_state != NULL) {
  62. /* We cannot start another CFRunloop and/or thread in the child
  63. process; CF aborts if you try or if you try to touch the thread
  64. at all to kill it. So the best we can do is ignore it from now
  65. on. This means we can't watch directories in the same way
  66. anymore (like other BSDs). It also means we cannot properly
  67. clean up the allocated resources; calling
  68. uv__fsevents_loop_delete from uv_loop_close will crash the
  69. process. So we sidestep the issue by pretending like we never
  70. started it in the first place.
  71. */
  72. uv__has_forked_with_cfrunloop = 1;
  73. uv__free(loop->cf_state);
  74. loop->cf_state = NULL;
  75. }
  76. #endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
  77. return err;
  78. }
  79. int uv__io_check_fd(uv_loop_t* loop, int fd) {
  80. struct kevent ev;
  81. int rc;
  82. rc = 0;
  83. EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
  84. if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL))
  85. rc = UV__ERR(errno);
  86. EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
  87. if (rc == 0)
  88. if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL))
  89. abort();
  90. return rc;
  91. }
  92. void uv__io_poll(uv_loop_t* loop, int timeout) {
  93. struct kevent events[1024];
  94. struct kevent* ev;
  95. struct timespec spec;
  96. unsigned int nevents;
  97. unsigned int revents;
  98. QUEUE* q;
  99. uv__io_t* w;
  100. sigset_t* pset;
  101. sigset_t set;
  102. uint64_t base;
  103. uint64_t diff;
  104. int have_signals;
  105. int filter;
  106. int fflags;
  107. int count;
  108. int nfds;
  109. int fd;
  110. int op;
  111. int i;
  112. if (loop->nfds == 0) {
  113. assert(QUEUE_EMPTY(&loop->watcher_queue));
  114. return;
  115. }
  116. nevents = 0;
  117. while (!QUEUE_EMPTY(&loop->watcher_queue)) {
  118. q = QUEUE_HEAD(&loop->watcher_queue);
  119. QUEUE_REMOVE(q);
  120. QUEUE_INIT(q);
  121. w = QUEUE_DATA(q, uv__io_t, watcher_queue);
  122. assert(w->pevents != 0);
  123. assert(w->fd >= 0);
  124. assert(w->fd < (int) loop->nwatchers);
  125. if ((w->events & POLLIN) == 0 && (w->pevents & POLLIN) != 0) {
  126. filter = EVFILT_READ;
  127. fflags = 0;
  128. op = EV_ADD;
  129. if (w->cb == uv__fs_event) {
  130. filter = EVFILT_VNODE;
  131. fflags = NOTE_ATTRIB | NOTE_WRITE | NOTE_RENAME
  132. | NOTE_DELETE | NOTE_EXTEND | NOTE_REVOKE;
  133. op = EV_ADD | EV_ONESHOT; /* Stop the event from firing repeatedly. */
  134. }
  135. EV_SET(events + nevents, w->fd, filter, op, fflags, 0, 0);
  136. if (++nevents == ARRAY_SIZE(events)) {
  137. if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL))
  138. abort();
  139. nevents = 0;
  140. }
  141. }
  142. if ((w->events & POLLOUT) == 0 && (w->pevents & POLLOUT) != 0) {
  143. EV_SET(events + nevents, w->fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
  144. if (++nevents == ARRAY_SIZE(events)) {
  145. if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL))
  146. abort();
  147. nevents = 0;
  148. }
  149. }
  150. if ((w->events & UV__POLLPRI) == 0 && (w->pevents & UV__POLLPRI) != 0) {
  151. EV_SET(events + nevents, w->fd, EV_OOBAND, EV_ADD, 0, 0, 0);
  152. if (++nevents == ARRAY_SIZE(events)) {
  153. if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL))
  154. abort();
  155. nevents = 0;
  156. }
  157. }
  158. w->events = w->pevents;
  159. }
  160. pset = NULL;
  161. if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
  162. pset = &set;
  163. sigemptyset(pset);
  164. sigaddset(pset, SIGPROF);
  165. }
  166. assert(timeout >= -1);
  167. base = loop->time;
  168. count = 48; /* Benchmarks suggest this gives the best throughput. */
  169. for (;; nevents = 0) {
  170. if (timeout != -1) {
  171. spec.tv_sec = timeout / 1000;
  172. spec.tv_nsec = (timeout % 1000) * 1000000;
  173. }
  174. if (pset != NULL)
  175. pthread_sigmask(SIG_BLOCK, pset, NULL);
  176. nfds = kevent(loop->backend_fd,
  177. events,
  178. nevents,
  179. events,
  180. ARRAY_SIZE(events),
  181. timeout == -1 ? NULL : &spec);
  182. if (pset != NULL)
  183. pthread_sigmask(SIG_UNBLOCK, pset, NULL);
  184. /* Update loop->time unconditionally. It's tempting to skip the update when
  185. * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
  186. * operating system didn't reschedule our process while in the syscall.
  187. */
  188. SAVE_ERRNO(uv__update_time(loop));
  189. if (nfds == 0) {
  190. assert(timeout != -1);
  191. return;
  192. }
  193. if (nfds == -1) {
  194. if (errno != EINTR)
  195. abort();
  196. if (timeout == 0)
  197. return;
  198. if (timeout == -1)
  199. continue;
  200. /* Interrupted by a signal. Update timeout and poll again. */
  201. goto update_timeout;
  202. }
  203. have_signals = 0;
  204. nevents = 0;
  205. assert(loop->watchers != NULL);
  206. loop->watchers[loop->nwatchers] = (void*) events;
  207. loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
  208. for (i = 0; i < nfds; i++) {
  209. ev = events + i;
  210. fd = ev->ident;
  211. /* Skip invalidated events, see uv__platform_invalidate_fd */
  212. if (fd == -1)
  213. continue;
  214. w = loop->watchers[fd];
  215. if (w == NULL) {
  216. /* File descriptor that we've stopped watching, disarm it.
  217. * TODO: batch up. */
  218. struct kevent events[1];
  219. EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
  220. if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL))
  221. if (errno != EBADF && errno != ENOENT)
  222. abort();
  223. continue;
  224. }
  225. if (ev->filter == EVFILT_VNODE) {
  226. assert(w->events == POLLIN);
  227. assert(w->pevents == POLLIN);
  228. w->cb(loop, w, ev->fflags); /* XXX always uv__fs_event() */
  229. nevents++;
  230. continue;
  231. }
  232. revents = 0;
  233. if (ev->filter == EVFILT_READ) {
  234. if (w->pevents & POLLIN) {
  235. revents |= POLLIN;
  236. w->rcount = ev->data;
  237. } else {
  238. /* TODO batch up */
  239. struct kevent events[1];
  240. EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
  241. if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL))
  242. if (errno != ENOENT)
  243. abort();
  244. }
  245. }
  246. if (ev->filter == EV_OOBAND) {
  247. if (w->pevents & UV__POLLPRI) {
  248. revents |= UV__POLLPRI;
  249. w->rcount = ev->data;
  250. } else {
  251. /* TODO batch up */
  252. struct kevent events[1];
  253. EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
  254. if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL))
  255. if (errno != ENOENT)
  256. abort();
  257. }
  258. }
  259. if (ev->filter == EVFILT_WRITE) {
  260. if (w->pevents & POLLOUT) {
  261. revents |= POLLOUT;
  262. w->wcount = ev->data;
  263. } else {
  264. /* TODO batch up */
  265. struct kevent events[1];
  266. EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
  267. if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL))
  268. if (errno != ENOENT)
  269. abort();
  270. }
  271. }
  272. if (ev->flags & EV_ERROR)
  273. revents |= POLLERR;
  274. if ((ev->flags & EV_EOF) && (w->pevents & UV__POLLRDHUP))
  275. revents |= UV__POLLRDHUP;
  276. if (revents == 0)
  277. continue;
  278. /* Run signal watchers last. This also affects child process watchers
  279. * because those are implemented in terms of signal watchers.
  280. */
  281. if (w == &loop->signal_io_watcher)
  282. have_signals = 1;
  283. else
  284. w->cb(loop, w, revents);
  285. nevents++;
  286. }
  287. if (have_signals != 0)
  288. loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
  289. loop->watchers[loop->nwatchers] = NULL;
  290. loop->watchers[loop->nwatchers + 1] = NULL;
  291. if (have_signals != 0)
  292. return; /* Event loop should cycle now so don't poll again. */
  293. if (nevents != 0) {
  294. if (nfds == ARRAY_SIZE(events) && --count != 0) {
  295. /* Poll for more events but don't block this time. */
  296. timeout = 0;
  297. continue;
  298. }
  299. return;
  300. }
  301. if (timeout == 0)
  302. return;
  303. if (timeout == -1)
  304. continue;
  305. update_timeout:
  306. assert(timeout > 0);
  307. diff = loop->time - base;
  308. if (diff >= (uint64_t) timeout)
  309. return;
  310. timeout -= diff;
  311. }
  312. }
  313. void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
  314. struct kevent* events;
  315. uintptr_t i;
  316. uintptr_t nfds;
  317. assert(loop->watchers != NULL);
  318. assert(fd >= 0);
  319. events = (struct kevent*) loop->watchers[loop->nwatchers];
  320. nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
  321. if (events == NULL)
  322. return;
  323. /* Invalidate events with same file descriptor */
  324. for (i = 0; i < nfds; i++)
  325. if ((int) events[i].ident == fd)
  326. events[i].ident = -1;
  327. }
  328. static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags) {
  329. uv_fs_event_t* handle;
  330. struct kevent ev;
  331. int events;
  332. const char* path;
  333. #if defined(F_GETPATH)
  334. /* MAXPATHLEN == PATH_MAX but the former is what XNU calls it internally. */
  335. char pathbuf[MAXPATHLEN];
  336. #endif
  337. handle = container_of(w, uv_fs_event_t, event_watcher);
  338. if (fflags & (NOTE_ATTRIB | NOTE_EXTEND))
  339. events = UV_CHANGE;
  340. else
  341. events = UV_RENAME;
  342. path = NULL;
  343. #if defined(F_GETPATH)
  344. /* Also works when the file has been unlinked from the file system. Passing
  345. * in the path when the file has been deleted is arguably a little strange
  346. * but it's consistent with what the inotify backend does.
  347. */
  348. if (fcntl(handle->event_watcher.fd, F_GETPATH, pathbuf) == 0)
  349. path = uv__basename_r(pathbuf);
  350. #endif
  351. handle->cb(handle, path, events, 0);
  352. if (handle->event_watcher.fd == -1)
  353. return;
  354. /* Watcher operates in one-shot mode, re-arm it. */
  355. fflags = NOTE_ATTRIB | NOTE_WRITE | NOTE_RENAME
  356. | NOTE_DELETE | NOTE_EXTEND | NOTE_REVOKE;
  357. EV_SET(&ev, w->fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, fflags, 0, 0);
  358. if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL))
  359. abort();
  360. }
  361. int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
  362. uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
  363. return 0;
  364. }
  365. int uv_fs_event_start(uv_fs_event_t* handle,
  366. uv_fs_event_cb cb,
  367. const char* path,
  368. unsigned int flags) {
  369. int fd;
  370. if (uv__is_active(handle))
  371. return UV_EINVAL;
  372. #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
  373. /* Nullify field to perform checks later */
  374. handle->cf_cb = NULL;
  375. handle->realpath = NULL;
  376. handle->realpath_len = 0;
  377. handle->cf_flags = flags;
  378. if (!uv__has_forked_with_cfrunloop) {
  379. int r;
  380. /* The fallback fd is not used */
  381. handle->event_watcher.fd = -1;
  382. handle->path = uv__strdup(path);
  383. if (handle->path == NULL)
  384. return UV_ENOMEM;
  385. handle->cb = cb;
  386. r = uv__fsevents_init(handle);
  387. if (r == 0) {
  388. uv__handle_start(handle);
  389. } else {
  390. uv__free(handle->path);
  391. handle->path = NULL;
  392. }
  393. return r;
  394. }
  395. #endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
  396. /* TODO open asynchronously - but how do we report back errors? */
  397. fd = open(path, O_RDONLY);
  398. if (fd == -1)
  399. return UV__ERR(errno);
  400. handle->path = uv__strdup(path);
  401. if (handle->path == NULL) {
  402. uv__close_nocheckstdio(fd);
  403. return UV_ENOMEM;
  404. }
  405. handle->cb = cb;
  406. uv__handle_start(handle);
  407. uv__io_init(&handle->event_watcher, uv__fs_event, fd);
  408. uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
  409. return 0;
  410. }
  411. int uv_fs_event_stop(uv_fs_event_t* handle) {
  412. int r;
  413. r = 0;
  414. if (!uv__is_active(handle))
  415. return 0;
  416. uv__handle_stop(handle);
  417. #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
  418. if (!uv__has_forked_with_cfrunloop)
  419. r = uv__fsevents_close(handle);
  420. #endif
  421. if (handle->event_watcher.fd != -1) {
  422. uv__io_close(handle->loop, &handle->event_watcher);
  423. uv__close(handle->event_watcher.fd);
  424. handle->event_watcher.fd = -1;
  425. }
  426. uv__free(handle->path);
  427. handle->path = NULL;
  428. return r;
  429. }
  430. void uv__fs_event_close(uv_fs_event_t* handle) {
  431. uv_fs_event_stop(handle);
  432. }