diff --git a/pkgs/racket-pkgs/racket-doc/scribblings/inside/ports.scrbl b/pkgs/racket-pkgs/racket-doc/scribblings/inside/ports.scrbl index 210651f8e8..377fc34bf1 100644 --- a/pkgs/racket-pkgs/racket-doc/scribblings/inside/ports.scrbl +++ b/pkgs/racket-pkgs/racket-doc/scribblings/inside/ports.scrbl @@ -800,8 +800,11 @@ is created, it remains findable via @cpp{scheme_fd_to_semaphore} for a particular read/write mode as long as @var{fd} has not become ready in the read/write mode since the creation of the semaphore, or unless @cpp{MZFD_REMOVE} has been used to remove the registered semaphore. -The @var{is_socket} argument indicates whether @var{fd} is a socket -or a filesystem descriptor (and the difference matters only for Windows). +The @var{is_socket} argument indicates whether @var{fd} is a socket or +a filesystem descriptor; the difference matters for Windows, and it +matters for BSD-based platforms where sockets are always supported and +other file descriptors are tested for whether they correspond to a +directory or regular file. The @var{mode} argument is one of the following: @@ -824,6 +827,19 @@ The @var{mode} argument is one of the following: @item{@cpp{MZFD_REMOVE} (= @cpp{5}) --- removes all recorded semaphores for @var{fd} (unregistering a poll with the operating system) and returns @cpp{NULL}.} + + @item{@cpp{MZFD_CREATE_VNODE} (= @cpp{6}) --- creates or finds a + semaphore to reflect whether @var{fd} changes; on some + platforms, @cpp{MZFD_CREATE_VNODE} is the same as + @cpp{MZFD_CREATE_READ}; on other platforms, only one or the + other can be used on a given file descriptor.} + + @item{@cpp{MZFD_CHECK_VNODE} (= @cpp{7}) --- like @cpp{MZFD_CHECK_READ}, + but to find a semaphore recorded via @cpp{MZFD_CREATE_VNODE}.} + + @item{@cpp{MZFD_REMOVE_VNODE} (= @cpp{8}) --- like @cpp{MZFD_REMOVE}, + but to remove a semaphore recorded via @cpp{MZFD_CREATE_VNODE}.} + ]} diff --git a/racket/src/racket/include/scheme.h b/racket/src/racket/include/scheme.h index 439c12f91e..c19ae77ac2 100644 --- a/racket/src/racket/include/scheme.h +++ b/racket/src/racket/include/scheme.h @@ -2107,6 +2107,7 @@ extern Scheme_Extension_Table *scheme_extension_table; #define MZFD_REMOVE 5 #define MZFD_CREATE_VNODE 6 #define MZFD_CHECK_VNODE 7 +#define MZFD_REMOVE_VNODE 8 /*========================================================================*/ diff --git a/racket/src/racket/src/port.c b/racket/src/racket/src/port.c index 3bb34d51ca..7b4a6eb682 100644 --- a/racket/src/racket/src/port.c +++ b/racket/src/racket/src/port.c @@ -6152,7 +6152,7 @@ void scheme_filesystem_change_evt_cancel(Scheme_Object *evt, void *ignored_data) fc->fd = 0; } # else - (void)scheme_fd_to_semaphore(fc->fd, MZFD_REMOVE, 0); + (void)scheme_fd_to_semaphore(fc->fd, MZFD_REMOVE_VNODE, 0); scheme_close_file_fd(fc->fd); scheme_post_sema_all(fc->sema); # endif diff --git a/racket/src/racket/src/thread.c b/racket/src/racket/src/thread.c index 5f82e91dd1..68f72398ea 100644 --- a/racket/src/racket/src/thread.c +++ b/racket/src/racket/src/thread.c @@ -3507,7 +3507,8 @@ Scheme_Object *scheme_fd_to_semaphore(intptr_t fd, int mode, int is_socket) if (!v && ((mode == MZFD_CHECK_READ) || (mode == MZFD_CHECK_WRITE) || (mode == MZFD_CHECK_VNODE) - || (mode == MZFD_REMOVE))) + || (mode == MZFD_REMOVE) + || (mode == MZFD_REMOVE_VNODE))) return NULL; if (!v) { @@ -3521,7 +3522,7 @@ Scheme_Object *scheme_fd_to_semaphore(intptr_t fd, int mode, int is_socket) e = MZ_GET_FDSET(scheme_semaphore_fd_set, 2); # endif - if (mode == MZFD_REMOVE) { + if ((mode == MZFD_REMOVE) || (mode == MZFD_REMOVE_VNODE)) { s = SCHEME_VEC_ELS(v)[0]; if (!SCHEME_FALSEP(s)) scheme_post_sema_all(s); @@ -3532,14 +3533,24 @@ Scheme_Object *scheme_fd_to_semaphore(intptr_t fd, int mode, int is_socket) scheme_hash_set(scheme_semaphore_fd_mapping, key, NULL); # ifdef HAVE_KQUEUE_SYSCALL { - GC_CAN_IGNORE struct kevent kev[3]; + GC_CAN_IGNORE struct kevent kev[2]; struct timespec timeout = {0, 0}; - int kr; - EV_SET(kev, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); - EV_SET(&kev[1], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); - EV_SET(&kev[2], fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL); + int kr, pos = 0; + if (mode == MZFD_REMOVE_VNODE) { + EV_SET(&kev[pos], fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL); + pos++; + } else { + if (SCHEME_TRUEP(SCHEME_VEC_ELS(v)[0])) { + EV_SET(&kev[pos], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); + pos++; + } + if (SCHEME_TRUEP(SCHEME_VEC_ELS(v)[1])) { + EV_SET(&kev[pos], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); + pos++; + } + } do { - kr = kevent(scheme_semaphore_fd_kqueue, kev, 3, NULL, 0, &timeout); + kr = kevent(scheme_semaphore_fd_kqueue, kev, pos, NULL, 0, &timeout); } while ((kr == -1) && (errno == EINTR)); log_kqueue_error("remove", kr); }