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 21#include "uv.h" 22#include "internal.h" 23 24#include <assert.h> 25#include <stdlib.h> 26#include <string.h> 27#include <errno.h> 28 29#include <sys/sysctl.h> 30#include <sys/types.h> 31#include <sys/event.h> 32#include <sys/time.h> 33#include <unistd.h> 34#include <fcntl.h> 35#include <time.h> 36 37/* 38 * Required on 39 * - Until at least FreeBSD 11.0 40 * - Older versions of Mac OS X 41 * 42 * http://www.boost.org/doc/libs/1_61_0/boost/asio/detail/kqueue_reactor.hpp 43 */ 44#ifndef EV_OOBAND 45#define EV_OOBAND EV_FLAG1 46#endif 47 48static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags); 49 50 51int uv__kqueue_init(uv_loop_t* loop) { 52 loop->backend_fd = kqueue(); 53 if (loop->backend_fd == -1) 54 return UV__ERR(errno); 55 56 uv__cloexec(loop->backend_fd, 1); 57 58 return 0; 59} 60 61 62#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 63static int uv__has_forked_with_cfrunloop; 64#endif 65 66int uv__io_fork(uv_loop_t* loop) { 67 int err; 68 loop->backend_fd = -1; 69 err = uv__kqueue_init(loop); 70 if (err) 71 return err; 72 73#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 74 if (loop->cf_state != NULL) { 75 /* We cannot start another CFRunloop and/or thread in the child 76 process; CF aborts if you try or if you try to touch the thread 77 at all to kill it. So the best we can do is ignore it from now 78 on. This means we can't watch directories in the same way 79 anymore (like other BSDs). It also means we cannot properly 80 clean up the allocated resources; calling 81 uv__fsevents_loop_delete from uv_loop_close will crash the 82 process. So we sidestep the issue by pretending like we never 83 started it in the first place. 84 */ 85 uv__store_relaxed(&uv__has_forked_with_cfrunloop, 1); 86 uv__free(loop->cf_state); 87 loop->cf_state = NULL; 88 } 89#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */ 90 return err; 91} 92 93 94int uv__io_check_fd(uv_loop_t* loop, int fd) { 95 struct kevent ev; 96 int rc; 97 98 rc = 0; 99 EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, 0); 100 if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL)) 101 rc = UV__ERR(errno); 102 103 EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0); 104 if (rc == 0) 105 if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL)) 106 abort(); 107 108 return rc; 109} 110 111 112void uv__io_poll(uv_loop_t* loop, int timeout) { 113 struct kevent events[1024]; 114 struct kevent* ev; 115 struct timespec spec; 116 unsigned int nevents; 117 unsigned int revents; 118 QUEUE* q; 119 uv__io_t* w; 120 uv_process_t* process; 121 sigset_t* pset; 122 sigset_t set; 123 uint64_t base; 124 uint64_t diff; 125 int have_signals; 126 int filter; 127 int fflags; 128 int count; 129 int nfds; 130 int fd; 131 int op; 132 int i; 133 int user_timeout; 134 int reset_timeout; 135 136 if (loop->nfds == 0) { 137 assert(QUEUE_EMPTY(&loop->watcher_queue)); 138 return; 139 } 140 141 nevents = 0; 142 143 while (!QUEUE_EMPTY(&loop->watcher_queue)) { 144 q = QUEUE_HEAD(&loop->watcher_queue); 145 QUEUE_REMOVE(q); 146 QUEUE_INIT(q); 147 148 w = QUEUE_DATA(q, uv__io_t, watcher_queue); 149 assert(w->pevents != 0); 150 assert(w->fd >= 0); 151 assert(w->fd < (int) loop->nwatchers); 152 153 if ((w->events & POLLIN) == 0 && (w->pevents & POLLIN) != 0) { 154 filter = EVFILT_READ; 155 fflags = 0; 156 op = EV_ADD; 157 158 if (w->cb == uv__fs_event) { 159 filter = EVFILT_VNODE; 160 fflags = NOTE_ATTRIB | NOTE_WRITE | NOTE_RENAME 161 | NOTE_DELETE | NOTE_EXTEND | NOTE_REVOKE; 162 op = EV_ADD | EV_ONESHOT; /* Stop the event from firing repeatedly. */ 163 } 164 165 EV_SET(events + nevents, w->fd, filter, op, fflags, 0, 0); 166 167 if (++nevents == ARRAY_SIZE(events)) { 168 if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL)) 169 abort(); 170 nevents = 0; 171 } 172 } 173 174 if ((w->events & POLLOUT) == 0 && (w->pevents & POLLOUT) != 0) { 175 EV_SET(events + nevents, w->fd, EVFILT_WRITE, EV_ADD, 0, 0, 0); 176 177 if (++nevents == ARRAY_SIZE(events)) { 178 if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL)) 179 abort(); 180 nevents = 0; 181 } 182 } 183 184 if ((w->events & UV__POLLPRI) == 0 && (w->pevents & UV__POLLPRI) != 0) { 185 EV_SET(events + nevents, w->fd, EV_OOBAND, EV_ADD, 0, 0, 0); 186 187 if (++nevents == ARRAY_SIZE(events)) { 188 if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL)) 189 abort(); 190 nevents = 0; 191 } 192 } 193 194 w->events = w->pevents; 195 } 196 197 pset = NULL; 198 if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { 199 pset = &set; 200 sigemptyset(pset); 201 sigaddset(pset, SIGPROF); 202 } 203 204 assert(timeout >= -1); 205 base = loop->time; 206 count = 48; /* Benchmarks suggest this gives the best throughput. */ 207 208 if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) { 209 reset_timeout = 1; 210 user_timeout = timeout; 211 timeout = 0; 212 } else { 213 reset_timeout = 0; 214 } 215 216 for (;; nevents = 0) { 217 /* Only need to set the provider_entry_time if timeout != 0. The function 218 * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME. 219 */ 220 if (timeout != 0) 221 uv__metrics_set_provider_entry_time(loop); 222 223 if (timeout != -1) { 224 spec.tv_sec = timeout / 1000; 225 spec.tv_nsec = (timeout % 1000) * 1000000; 226 } 227 228 if (pset != NULL) 229 pthread_sigmask(SIG_BLOCK, pset, NULL); 230 231 nfds = kevent(loop->backend_fd, 232 events, 233 nevents, 234 events, 235 ARRAY_SIZE(events), 236 timeout == -1 ? NULL : &spec); 237 238 if (pset != NULL) 239 pthread_sigmask(SIG_UNBLOCK, pset, NULL); 240 241 /* Update loop->time unconditionally. It's tempting to skip the update when 242 * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the 243 * operating system didn't reschedule our process while in the syscall. 244 */ 245 SAVE_ERRNO(uv__update_time(loop)); 246 247 if (nfds == 0) { 248 if (reset_timeout != 0) { 249 timeout = user_timeout; 250 reset_timeout = 0; 251 if (timeout == -1) 252 continue; 253 if (timeout > 0) 254 goto update_timeout; 255 } 256 257 assert(timeout != -1); 258 return; 259 } 260 261 if (nfds == -1) { 262 if (errno != EINTR) 263 abort(); 264 265 if (reset_timeout != 0) { 266 timeout = user_timeout; 267 reset_timeout = 0; 268 } 269 270 if (timeout == 0) 271 return; 272 273 if (timeout == -1) 274 continue; 275 276 /* Interrupted by a signal. Update timeout and poll again. */ 277 goto update_timeout; 278 } 279 280 have_signals = 0; 281 nevents = 0; 282 283 assert(loop->watchers != NULL); 284 loop->watchers[loop->nwatchers] = (void*) events; 285 loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; 286 for (i = 0; i < nfds; i++) { 287 ev = events + i; 288 fd = ev->ident; 289 290 /* Handle kevent NOTE_EXIT results */ 291 if (ev->filter == EVFILT_PROC) { 292 QUEUE_FOREACH(q, &loop->process_handles) { 293 process = QUEUE_DATA(q, uv_process_t, queue); 294 if (process->pid == fd) { 295 process->flags |= UV_HANDLE_REAP; 296 loop->flags |= UV_LOOP_REAP_CHILDREN; 297 break; 298 } 299 } 300 nevents++; 301 continue; 302 } 303 304 /* Skip invalidated events, see uv__platform_invalidate_fd */ 305 if (fd == -1) 306 continue; 307 w = loop->watchers[fd]; 308 309 if (w == NULL) { 310 /* File descriptor that we've stopped watching, disarm it. 311 * TODO: batch up. */ 312 struct kevent events[1]; 313 314 EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); 315 if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) 316 if (errno != EBADF && errno != ENOENT) 317 abort(); 318 319 continue; 320 } 321 322 if (ev->filter == EVFILT_VNODE) { 323 assert(w->events == POLLIN); 324 assert(w->pevents == POLLIN); 325 uv__metrics_update_idle_time(loop); 326 w->cb(loop, w, ev->fflags); /* XXX always uv__fs_event() */ 327 nevents++; 328 continue; 329 } 330 331 revents = 0; 332 333 if (ev->filter == EVFILT_READ) { 334 if (w->pevents & POLLIN) { 335 revents |= POLLIN; 336 w->rcount = ev->data; 337 } else { 338 /* TODO batch up */ 339 struct kevent events[1]; 340 EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); 341 if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) 342 if (errno != ENOENT) 343 abort(); 344 } 345 if ((ev->flags & EV_EOF) && (w->pevents & UV__POLLRDHUP)) 346 revents |= UV__POLLRDHUP; 347 } 348 349 if (ev->filter == EV_OOBAND) { 350 if (w->pevents & UV__POLLPRI) { 351 revents |= UV__POLLPRI; 352 w->rcount = ev->data; 353 } else { 354 /* TODO batch up */ 355 struct kevent events[1]; 356 EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); 357 if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) 358 if (errno != ENOENT) 359 abort(); 360 } 361 } 362 363 if (ev->filter == EVFILT_WRITE) { 364 if (w->pevents & POLLOUT) { 365 revents |= POLLOUT; 366 w->wcount = ev->data; 367 } else { 368 /* TODO batch up */ 369 struct kevent events[1]; 370 EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); 371 if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) 372 if (errno != ENOENT) 373 abort(); 374 } 375 } 376 377 if (ev->flags & EV_ERROR) 378 revents |= POLLERR; 379 380 if (revents == 0) 381 continue; 382 383 /* Run signal watchers last. This also affects child process watchers 384 * because those are implemented in terms of signal watchers. 385 */ 386 if (w == &loop->signal_io_watcher) { 387 have_signals = 1; 388 } else { 389 uv__metrics_update_idle_time(loop); 390 w->cb(loop, w, revents); 391 } 392 393 nevents++; 394 } 395 396 if (loop->flags & UV_LOOP_REAP_CHILDREN) { 397 loop->flags &= ~UV_LOOP_REAP_CHILDREN; 398 uv__wait_children(loop); 399 } 400 401 if (reset_timeout != 0) { 402 timeout = user_timeout; 403 reset_timeout = 0; 404 } 405 406 if (have_signals != 0) { 407 uv__metrics_update_idle_time(loop); 408 loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); 409 } 410 411 loop->watchers[loop->nwatchers] = NULL; 412 loop->watchers[loop->nwatchers + 1] = NULL; 413 414 if (have_signals != 0) 415 return; /* Event loop should cycle now so don't poll again. */ 416 417 if (nevents != 0) { 418 if (nfds == ARRAY_SIZE(events) && --count != 0) { 419 /* Poll for more events but don't block this time. */ 420 timeout = 0; 421 continue; 422 } 423 return; 424 } 425 426 if (timeout == 0) 427 return; 428 429 if (timeout == -1) 430 continue; 431 432update_timeout: 433 assert(timeout > 0); 434 435 diff = loop->time - base; 436 if (diff >= (uint64_t) timeout) 437 return; 438 439 timeout -= diff; 440 } 441} 442 443 444void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { 445 struct kevent* events; 446 uintptr_t i; 447 uintptr_t nfds; 448 449 assert(loop->watchers != NULL); 450 assert(fd >= 0); 451 452 events = (struct kevent*) loop->watchers[loop->nwatchers]; 453 nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; 454 if (events == NULL) 455 return; 456 457 /* Invalidate events with same file descriptor */ 458 for (i = 0; i < nfds; i++) 459 if ((int) events[i].ident == fd && events[i].filter != EVFILT_PROC) 460 events[i].ident = -1; 461} 462 463 464static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags) { 465 uv_fs_event_t* handle; 466 struct kevent ev; 467 int events; 468 const char* path; 469#if defined(F_GETPATH) 470 /* MAXPATHLEN == PATH_MAX but the former is what XNU calls it internally. */ 471 char pathbuf[MAXPATHLEN]; 472#endif 473 474 handle = container_of(w, uv_fs_event_t, event_watcher); 475 476 if (fflags & (NOTE_ATTRIB | NOTE_EXTEND)) 477 events = UV_CHANGE; 478 else 479 events = UV_RENAME; 480 481 path = NULL; 482#if defined(F_GETPATH) 483 /* Also works when the file has been unlinked from the file system. Passing 484 * in the path when the file has been deleted is arguably a little strange 485 * but it's consistent with what the inotify backend does. 486 */ 487 if (fcntl(handle->event_watcher.fd, F_GETPATH, pathbuf) == 0) 488 path = uv__basename_r(pathbuf); 489#endif 490 handle->cb(handle, path, events, 0); 491 492 if (handle->event_watcher.fd == -1) 493 return; 494 495 /* Watcher operates in one-shot mode, re-arm it. */ 496 fflags = NOTE_ATTRIB | NOTE_WRITE | NOTE_RENAME 497 | NOTE_DELETE | NOTE_EXTEND | NOTE_REVOKE; 498 499 EV_SET(&ev, w->fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, fflags, 0, 0); 500 501 if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL)) 502 abort(); 503} 504 505 506int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { 507 uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); 508 return 0; 509} 510 511 512int uv_fs_event_start(uv_fs_event_t* handle, 513 uv_fs_event_cb cb, 514 const char* path, 515 unsigned int flags) { 516 int fd; 517#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 518 struct stat statbuf; 519#endif 520 521 if (uv__is_active(handle)) 522 return UV_EINVAL; 523 524 handle->cb = cb; 525 handle->path = uv__strdup(path); 526 if (handle->path == NULL) 527 return UV_ENOMEM; 528 529 /* TODO open asynchronously - but how do we report back errors? */ 530 fd = open(handle->path, O_RDONLY); 531 if (fd == -1) { 532 uv__free(handle->path); 533 handle->path = NULL; 534 return UV__ERR(errno); 535 } 536 537#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 538 /* Nullify field to perform checks later */ 539 handle->cf_cb = NULL; 540 handle->realpath = NULL; 541 handle->realpath_len = 0; 542 handle->cf_flags = flags; 543 544 if (fstat(fd, &statbuf)) 545 goto fallback; 546 /* FSEvents works only with directories */ 547 if (!(statbuf.st_mode & S_IFDIR)) 548 goto fallback; 549 550 if (0 == uv__load_relaxed(&uv__has_forked_with_cfrunloop)) { 551 int r; 552 /* The fallback fd is no longer needed */ 553 uv__close_nocheckstdio(fd); 554 handle->event_watcher.fd = -1; 555 r = uv__fsevents_init(handle); 556 if (r == 0) { 557 uv__handle_start(handle); 558 } else { 559 uv__free(handle->path); 560 handle->path = NULL; 561 } 562 return r; 563 } 564fallback: 565#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */ 566 567 uv__handle_start(handle); 568 uv__io_init(&handle->event_watcher, uv__fs_event, fd); 569 uv__io_start(handle->loop, &handle->event_watcher, POLLIN); 570 571 return 0; 572} 573 574 575int uv_fs_event_stop(uv_fs_event_t* handle) { 576 int r; 577 r = 0; 578 579 if (!uv__is_active(handle)) 580 return 0; 581 582 uv__handle_stop(handle); 583 584#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 585 if (0 == uv__load_relaxed(&uv__has_forked_with_cfrunloop)) 586 if (handle->cf_cb != NULL) 587 r = uv__fsevents_close(handle); 588#endif 589 590 if (handle->event_watcher.fd != -1) { 591 uv__io_close(handle->loop, &handle->event_watcher); 592 uv__close(handle->event_watcher.fd); 593 handle->event_watcher.fd = -1; 594 } 595 596 uv__free(handle->path); 597 handle->path = NULL; 598 599 return r; 600} 601 602 603void uv__fs_event_close(uv_fs_event_t* handle) { 604 uv_fs_event_stop(handle); 605} 606