diff --git a/racket/src/rktio/Makefile.in b/racket/src/rktio/Makefile.in index 5076fbb10f..9c54644226 100644 --- a/racket/src/rktio/Makefile.in +++ b/racket/src/rktio/Makefile.in @@ -8,7 +8,7 @@ LIBS = @LIBS@ RKTIO_HEADERS = $(srcdir)/rktio.h $(srcdir)/rktio_private.h rktio_config.h -OBJS = rktio_filesystem.o \ +OBJS = rktio_fs.o \ rktio_fd.o \ rktio_file.o \ rktio_poll_set.o \ @@ -16,6 +16,7 @@ OBJS = rktio_filesystem.o \ rktio_network.o \ rktio_process.o \ rktio_envvars.o \ + rktio_fs_change.o \ rktio_error.o \ rktio_main.o @@ -30,8 +31,8 @@ rktio_demo: $(OBJS) demo.o demo_fifo demo_fifo: mkfifo demo_fifo -rktio_filesystem.o: $(srcdir)/rktio_filesystem.c $(RKTIO_HEADERS) - $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_filesystem.o -c $(srcdir)/rktio_filesystem.c +rktio_fs.o: $(srcdir)/rktio_fs.c $(RKTIO_HEADERS) + $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_fs.o -c $(srcdir)/rktio_fs.c rktio_fd.o: $(srcdir)/rktio_fd.c $(RKTIO_HEADERS) $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_fd.o -c $(srcdir)/rktio_fd.c @@ -54,6 +55,9 @@ rktio_process.o: $(srcdir)/rktio_process.c $(RKTIO_HEADERS) rktio_envvars.o: $(srcdir)/rktio_envvars.c $(RKTIO_HEADERS) $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_envvars.o -c $(srcdir)/rktio_envvars.c +rktio_fs_change.o: $(srcdir)/rktio_fs_change.c $(RKTIO_HEADERS) + $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_fs_change.o -c $(srcdir)/rktio_fs_change.c + rktio_error.o: $(srcdir)/rktio_error.c $(RKTIO_HEADERS) $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_error.o -c $(srcdir)/rktio_error.c diff --git a/racket/src/rktio/demo.c b/racket/src/rktio/demo.c index c892eba141..f21bc933ef 100644 --- a/racket/src/rktio/demo.c +++ b/racket/src/rktio/demo.c @@ -882,6 +882,43 @@ int main(int argc, char **argv) rktio_forget(rktio, err_fd); } + /* Filesystem-change events */ + + if (rktio_fs_change_properties(rktio) & RKTIO_FS_CHANGE_SUPPORTED) { + char *path = "test1"; + rktio_fs_change_t *fc; + rktio_poll_set_t *ps; + + if (verbose) + printf("fs change\n"); + + fc = rktio_fs_change(rktio, path); + check_valid(fc); + + check_valid(!rktio_poll_fs_change_ready(rktio, fc)); + + ps = rktio_make_poll_set(rktio); + check_valid(ps); + rktio_poll_add_fs_change(rktio, fc, ps); + + rktio_sleep(rktio, 0.1, ps, NULL); + /* FIXME: check that at least 0.1 seconds have passed */ + + fd2 = rktio_open(rktio, "test1", RKTIO_OPEN_WRITE | RKTIO_OPEN_CAN_EXIST); + check_valid(fd2); + amt = rktio_write(rktio, fd2, "hola", 4); + check_valid(amt == 4); + + rktio_sleep(rktio, 0, ps, NULL); + check_valid(rktio_poll_fs_change_ready(rktio, fc) == RKTIO_POLL_READY); + check_valid(rktio_poll_fs_change_ready(rktio, fc) == RKTIO_POLL_READY); + + check_valid(rktio_close(rktio, fd2)); + rktio_poll_set_close(rktio, ps); + + rktio_fs_change_forget(rktio, fc); + } + if (verbose) printf("done\n"); diff --git a/racket/src/rktio/rktio.h b/racket/src/rktio/rktio.h index 74138c0de5..45c2c13a10 100644 --- a/racket/src/rktio/rktio.h +++ b/racket/src/rktio/rktio.h @@ -200,6 +200,22 @@ rktio_status_t *rktio_process_status(rktio_t *rktio, rktio_process_t *sp); void rktio_block_child_signals(rktio_t*rktio, int block); +/*************************************************/ +/* Filesystem-change events */ + +#define RKTIO_FS_CHANGE_SUPPORTED (1 << 0) +#define RKTIO_FS_CHANGE_SCALABLE (1 << 1) +#define RKTIO_FS_CHANGE_LOW_LATENCY (1 << 2) +#define RKTIO_FS_CHANGE_FILE_LEVEL (1 << 3) + +int rktio_fs_change_properties(rktio_t *rktio); + +typedef struct rktio_fs_change_t rktio_fs_change_t; + +rktio_fs_change_t *rktio_fs_change(rktio_t *rktio, char *path); +void rktio_fs_change_forget(rktio_t *rktio, rktio_fs_change_t *fc); +int rktio_poll_fs_change_ready(rktio_t *rktio, rktio_fs_change_t *fc); + /*************************************************/ /* File-descriptor sets for polling */ @@ -219,6 +235,7 @@ void rktio_poll_add_receive(rktio_t *rktio, rktio_listener_t *listener, rktio_po void rktio_poll_add_connect(rktio_t *rktio, rktio_connect_t *conn, rktio_poll_set_t *fds); void rktio_poll_add_addrinfo_lookup(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup, rktio_poll_set_t *fds); void rktio_poll_add_process(rktio_t *rktio, rktio_process_t *sp, rktio_poll_set_t *fds); +void rktio_poll_add_fs_change(rktio_t *rktio, rktio_fs_change_t *fc, rktio_poll_set_t *fds); void rktio_poll_set_add_nosleep(rktio_t *rktio, rktio_poll_set_t *fds); @@ -243,6 +260,7 @@ enum { RKTIO_LTPS_CHECK_READ, RKTIO_LTPS_CHECK_WRITE, RKTIO_LTPS_REMOVE, + /* Internal, for filesystem-change events with kqueue: */ RKTIO_LTPS_CREATE_VNODE, RKTIO_LTPS_CHECK_VNODE, RKTIO_LTPS_REMOVE_VNODE diff --git a/racket/src/rktio/rktio_fd.c b/racket/src/rktio/rktio_fd.c index f1c4c9aed2..d465ccb6f8 100644 --- a/racket/src/rktio/rktio_fd.c +++ b/racket/src/rktio/rktio_fd.c @@ -196,6 +196,15 @@ rktio_fd_t *rktio_dup(rktio_t *rktio, rktio_fd_t *rfd) /* closing */ /*************************************************************/ +#ifdef RKTIO_SYSTEM_UNIX +void rktio_reliably_close(intptr_t s) { + int cr; + do { + cr = close(s); + } while ((cr == -1) && (errno == EINTR)); +} +#endif + int rktio_close(rktio_t *rktio, rktio_fd_t *rfd) { #ifdef RKTIO_SYSTEM_UNIX @@ -206,9 +215,7 @@ int rktio_close(rktio_t *rktio, rktio_fd_t *rfd) release_lockf(rfd->fd); # endif - do { - cr = close(rfd->fd); - } while ((cr == -1) && (errno == EINTR)); + rktio_reliably_close(rfd->fd); #endif #ifdef RKTIO_SYSTEM_WINDOWS if (rfd->modes & RKTIO_OPEN_SOCKET) diff --git a/racket/src/rktio/rktio_file.c b/racket/src/rktio/rktio_file.c index 186f9ab87f..a228defc9f 100644 --- a/racket/src/rktio/rktio_file.c +++ b/racket/src/rktio/rktio_file.c @@ -12,10 +12,6 @@ # include #endif -#ifndef RKTIO_BINARY -# define RKTIO_BINARY 0 -#endif - /*************************************************************/ /* opening a file fd */ /*************************************************************/ diff --git a/racket/src/rktio/rktio_filesystem.c b/racket/src/rktio/rktio_fs.c similarity index 100% rename from racket/src/rktio/rktio_filesystem.c rename to racket/src/rktio/rktio_fs.c diff --git a/racket/src/rktio/rktio_fs_change.c b/racket/src/rktio/rktio_fs_change.c new file mode 100644 index 0000000000..f2e99d1b11 --- /dev/null +++ b/racket/src/rktio/rktio_fs_change.c @@ -0,0 +1,522 @@ +#include "rktio.h" +#include "rktio_private.h" +#include +#include +#include +#if defined(HAVE_KQUEUE_SYSCALL) +# include +#endif +#if defined(HAVE_INOTIFY_SYSCALL) +# include +# include +#endif + +#if defined(HAVE_KQUEUE_SYSCALL) \ + || defined(RKTIO_SYSTEM_WINDOWS) \ + || defined(HAVE_INOTIFY_SYSCALL) \ + || defined(FILESYSTEM_NEVER_CHANGES) +# define HAVE_FILESYSTEM_CHANGE_EVTS +#else +# define NO_FILESYSTEM_CHANGE_EVTS +#endif + +#if defined(HAVE_INOTIFY_SYSCALL) +static void do_inotify_init(rktio_t *rktio); +static int do_inotify_ready(rktio_t *rktio); +static int do_inotify_errid(rktio_t *rktio); +static int do_inotify_add(rktio_t *rktio, char *filename); +static void do_inotify_remove(rktio_t *rktio, int p2); +static int do_inotify_poll(rktio_t *rktio, int p2); +static void do_inotify_stop(rktio_t *rktio); +static int do_inotify_fd(rktio_t *rktio); +#endif + +/*========================================================================*/ +/* Common type and functions */ +/*========================================================================*/ + +struct rktio_fs_change_t { + int done; + intptr_t fd; +#if defined(HAVE_KQUEUE_SYSCALL) && !defined(FILESYSTEM_NEVER_CHANGES) + rktio_ltps_t *lt; + rktio_ltps_handle_t *lth; +#endif +}; + +int rktio_fs_change_properties(rktio_t *rktio) +{ + int flags = 0; + +#ifdef NO_FILESYSTEM_CHANGE_EVTS +#else + flags |= RKTIO_FS_CHANGE_SUPPORTED; +# if !defined(HAVE_KQUEUE_SYSCALL) + flags |= RKTIO_FS_CHANGE_SCALABLE; +# endif +# if !defined(HAVE_INOTIFY_SYSCALL) + flags |= RKTIO_FS_CHANGE_LOW_LATENCY; +# endif +# if !defined(RKTIO_SYSTEM_WINDOWS) + flags |= RKTIO_FS_CHANGE_FILE_LEVEL; +# endif +#endif + + return flags; +} + +rktio_fs_change_t *rktio_fs_change(rktio_t *rktio, char *path) +{ + int ok = 0; +#ifndef NO_FILESYSTEM_CHANGE_EVTS + int errid = 0; +# if defined(HAVE_KQUEUE_SYSCALL) + rktio_ltps_t *lt; + rktio_ltps_handle_t *lth; +# endif +#endif + intptr_t fd; + rktio_fs_change_t *fc; + + fd = 0; + +#if defined(NO_FILESYSTEM_CHANGE_EVTS) + set_racket_error(RKTIO_ERROR_UNSUPPORTED); + ok = 0; +#elif defined(FILESYSTEM_NEVER_CHANGES) + ok = 1; +#elif defined(HAVE_KQUEUE_SYSCALL) + do { + fd = open(path, RKTIO_BINARY, 0666); + } while ((fd == -1) && (errno == EINTR)); + if (fd == -1) + get_posix_error(); + else { + rktio_fd_t *rfd; + rfd = rktio_system_fd(rktio, fd, 0); + lt = rktio_open_ltps(rktio); + if (lt) + lth = rktio_ltps_add(rktio, lt, rfd, RKTIO_LTPS_CREATE_VNODE); + if (!lt || !lth) { + if (lt) + rktio_ltps_close(rktio, lt); + rktio_reliably_close(fd); + } else + ok = 1; + rktio_forget(rktio, rfd); + } +#elif defined(HAVE_INOTIFY_SYSCALL) + do_inotify_init(rktio); + if (!do_inotify_ready(rktio)) { + errno = do_inotify_errid(rktio); + get_posix_error(); + } else { + fd = do_inotify_add(rktio, path); + if (fd == -1) + get_posix_error(); + else + ok = 1; + } +#elif defined(RKTIO_SYSTEM_WINDOWS) + { + HANDLE h; + + h = FindFirstChangeNotificationW(WIDE_PATH_tmp(try_path), FALSE, + (FILE_NOTIFY_CHANGE_FILE_NAME + | FILE_NOTIFY_CHANGE_DIR_NAME + | FILE_NOTIFY_CHANGE_SIZE + | FILE_NOTIFY_CHANGE_LAST_WRITE + | FILE_NOTIFY_CHANGE_ATTRIBUTES)); + if (h == INVALID_HANDLE_VALUE) + set_windows_error(); + else { + fd = (intptr_t)h; + ok = 1; + } + } +#endif + + if (!ok) + return NULL; + + fc = malloc(sizeof(rktio_fs_change_t)); + fc->done = 0; + fc->fd = fd; +#if defined(HAVE_KQUEUE_SYSCALL) && !defined(NO_FILESYSTEM_CHANGE_EVTS) + fc->lt = lt; + fc->lth = lth; +#endif + + return fc; +} + +static void fs_change_release(rktio_t *rktio, rktio_fs_change_t *fc) +{ + if (fc->done) + return; + +# if defined(FILESYSTEM_NEVER_CHANGES) + /* nothing to do */ +# elif defined(RKTIO_SYSTEM_WINDOWS) + FindCloseChangeNotification((HANDLE)fc->fd); +# elif defined(HAVE_INOTIFY_SYSCALL) + do_inotify_remove(rktio, fc->fd); +# elif defined(HAVE_KQUEUE_SYSCALL) + rktio_ltps_close(rktio, fc->lt); + free(fc->lth); + rktio_reliably_close(fc->fd); +#endif + + fc->done = 1; +} + +void rktio_fs_change_forget(rktio_t *rktio, rktio_fs_change_t *fc) +{ + fs_change_release(rktio, fc); + free(fc); +} + +int rktio_poll_fs_change_ready(rktio_t *rktio, rktio_fs_change_t *fc) +{ +#if defined(NO_FILESYSTEM_CHANGE_EVTS) + return 0; +#elif defined(RKTIO_SYSTEM_WINDOWS) + if (!fc->done) { + if (WaitForSingleObject((HANDLE)fc->fd, 0) == WAIT_OBJECT_0) + fs_change_release(rktio, fc); + } + + return (fc->done ? RKTIO_POLL_READY : 0); +#elif defined(HAVE_INOTIFY_SYSCALL) + if (!fc->done) { + int r = do_inotify_poll(rktio, fc->fd); + if (r < 0) + return RKTIO_POLL_ERROR; + if (r) + fs_change_release(rktio, fc); + } + + return (fc->done ? RKTIO_POLL_READY : 0); +#elif defined(FILESYSTEM_NEVER_CHANGES) + return 0; +#elif defined(HAVE_KQUEUE_SYSCALL) + if (!fc->done) { + if (rktio_ltps_poll(rktio, fc->lt)) + if (rktio_ltps_get_signaled_handle(rktio, fc->lt) == fc->lth) + fs_change_release(rktio, fc); + } + + return (fc->done ? RKTIO_POLL_READY : 0); +#endif +} + +void rktio_poll_add_fs_change(rktio_t *rktio, rktio_fs_change_t *fc, rktio_poll_set_t *fds) +{ + if (fc->done) { + rktio_poll_set_add_nosleep(rktio, fds); + return; + } + +#if defined(NO_FILESYSTEM_CHANGE_EVTS) +#elif defined(RKTIO_SYSTEM_WINDOWS) + rktio_poll_set_add_handle(rktio, (HANDLE)fc->fd, fds, 0); +#elif defined(HAVE_INOTIFY_SYSCALL) + int fd; + fd = do_inotify_fd(rktio); + if (fd >= 0) { + rktio_poll_set_t *fds2; + RKTIO_FD_SET(fd, fds); + fds2 = RKTIO_GET_FDSET(fds, 2); + RKTIO_FD_SET(fd, fds2); + } else if (fd == -2) { + rktio_poll_set_add_nosleep(rktio, fds); + } +#elif defined(FILESYSTEM_NEVER_CHANGES) +#elif defined(HAVE_KQUEUE_SYSCALL) + { + int fd = rktio_ltps_get_fd(fc->lt); + rktio_poll_set_t *fds2; + RKTIO_FD_SET(fd, fds); + fds2 = RKTIO_GET_FDSET(fds, 2); + RKTIO_FD_SET(fd, fds2); + } +#endif +} + +void rktio_stop_fs_change(rktio_t *rktio) +{ +#ifdef HAVE_INOTIFY_SYSCALL + do_inotify_stop(rktio); +#endif +} + +/*========================================================================*/ +/* inotify */ +/*========================================================================*/ + +/* Multiplex multiple filesystem change events onto a single + inotify connection. That's almost as easy as using watch + descriptors in place of file descriptors, but using the + same filesystem path multiple times produces the same + watch descriptors, so reference-count it. Also, each watch + can be removed as soon as it fires, since filesystem + change events are single-shot. + + The values returned by do_inotify_add() are indices into an array + of watch descriptors. There's room for a better data structure if + the watch-descriptor-to-index mapping becomes too slow. */ + +#ifdef HAVE_INOTIFY_SYSCALL + +typedef struct rin_wd_t { + int wd; + int refcount; + int val; +} rin_wd_t; + +typedef struct rin_inotify_state_t { + int ready, errid, fd; + rin_wd_t *wds; + int size, count; + int got; +} rin_inotify_state_t; + +static int rin_find_wd(int wd, rin_wd_t *wds, int size) +{ + int i; + for (i = 0; i < size; i++) { + if (wds[i].wd == wd) return i; + } + + return -1; +} + +static int rin_add_wd(int wd, rin_wd_t *wds, int size) +{ + int i; + + for (i = 0; i < size; i++) { + if (wds[i].wd == wd) { + wds[i].refcount++; + return i; + } + } + + for (i = 0; i < size; i++) { + if (!wds[i].refcount) { + wds[i].wd = wd; + wds[i].refcount = 1; + wds[i].val = 0; + return i; + } + } + + abort(); + return -1; +} + +static int rin_pull_events(rktio_t *rktio, int fd, rin_wd_t *wds, int size) +{ + struct inotify_event _ev, *ev; + void *b = NULL; + int rc, p, got = 0; + int bsize; + struct pollfd pfd[1]; + + ev = &_ev; + bsize = sizeof(_ev); + + pfd[0].fd = fd; + pfd[0].events = POLLIN; + + while (poll(pfd, 1, 0)) { + rc = read(fd, ev, bsize); + if (rc > 0) { + p = rin_find_wd(ev->wd, wds, size); + if (p != -1) { + got = 1; + wds[p].val = 1; + wds[p].wd = -1; + inotify_rm_watch(fd, ev->wd); + } + } else if (rc == -1) { + if (errno == EAGAIN) + break; + else if (errno == EINTR) { + /* try again */ + } else if (errno == EINVAL) { + bsize *= 2; + if (b) free(b); + b = malloc(bsize); + ev = (struct inotify_event *)b; + } else { + get_posix_error(); + return -1; + } + } else + break; + } + + if (b) + free (b); + + return got; +} + +static void rin_inotify_start(rin_inotify_state_t *s) +{ + int fd; + + fd = inotify_init(); + if (fd == -1) { + s->errid = errno; + } else { + s->errid = 0; + s->ready = 1; + s->fd = fd; + } +} + +static void rin_inotify_end(rin_inotify_state_t *s) +{ + int rc; + + if (s->ready) { + do { + rc = close(s->fd); + } while (rc == -1 && errno == EINTR); + } + + if (s->wds) free(s->wds); + + free(s); +} + +static void do_inotify_init(rktio_t *rktio) +{ + rin_inotify_state_t *s = rktio->inotify_server; + + if (!s) { + s = (rin_inotify_state_t *)malloc(sizeof(rin_inotify_state_t)); + memset(s, 0, sizeof(rin_inotify_state_t)); + + rktio->inotify_server = s; + } + + if (!s->ready) + rin_inotify_start(s); +} + +static int do_inotify_ready(rktio_t *rktio) +{ + rin_inotify_state_t *s = rktio->inotify_server; + + return s->ready; +} + +static int do_inotify_errid(rktio_t *rktio) +{ + rin_inotify_state_t *s = rktio->inotify_server; + + return s->errid; +} + +/* Other functions are called only if do_inotify_ready() returns 1. */ + +static int do_inotify_add(rktio_t *rktio, char *filename) +{ + rin_inotify_state_t *s = rktio->inotify_server; + int wd; + + if (s->count == s->size) { + int new_size = (s->size ? (2 * s->size) : 32); + rin_wd_t *new_wds; + int i; + new_wds = (rin_wd_t *)malloc(sizeof(rin_wd_t) * new_size); + memcpy(new_wds, s->wds, s->size * sizeof(rin_wd_t)); + if (s->wds) free(s->wds); + s->wds = new_wds; + s->size = new_size; + for (i = s->count; i < s->size; i++) + { + s->wds[i].wd = -1; + s->wds[i].refcount = 0; + } + } + + wd = inotify_add_watch(s->fd, filename, + (IN_CREATE | IN_DELETE | IN_DELETE_SELF + | IN_MODIFY | IN_MOVE_SELF | IN_MOVED_TO + | IN_ATTRIB | IN_ONESHOT)); + + if (wd == -1) + return -1; + else { + int p; + + p = rin_add_wd(wd, s->wds, s->size); + if (s->wds[p].refcount == 1) + s->count++; + + return p+1; + } +} + +static void do_inotify_remove(rktio_t *rktio, int p2) +{ + rin_inotify_state_t *s = rktio->inotify_server; + int p = p2 - 1; + + if (s->wds[p].refcount == 1) { + if (s->wds[p].wd != -1) { + inotify_rm_watch(s->fd, s->wds[p].wd); + s->wds[p].wd = -1; + /* in case the wd gets reused: */ + if (rin_pull_events(rktio, s->fd, s->wds, s->size) > 0) + s->got = 1; + } + --s->count; + } + s->wds[p].refcount -= 1; +} + +static int do_inotify_poll(rktio_t *rktio, int p2) +{ + rin_inotify_state_t *s = rktio->inotify_server; + int p = p2 - 1, r; + + r = rin_pull_events(rktio, s->fd, s->wds, s->size); + if (r > 0) + s->got = 1; + + if (r < 0) + return -1; + else if (s->wds[p].val) + return 1; + else + return 0; +} + +static void do_inotify_stop(rktio_t *rktio) +{ + rin_inotify_state_t *s = rktio->inotify_server; + + if (s) { + rin_inotify_end(s); + rktio->inotify_server = NULL; + } +} + +static int do_inotify_fd(rktio_t *rktio) +{ + rin_inotify_state_t *s = rktio->inotify_server; + + if (s->got) { + /* In case we received something for Y in a poll for X */ + s->got = 0; + return -2; + } + + return s->fd; +} +#endif diff --git a/racket/src/rktio/rktio_main.c b/racket/src/rktio/rktio_main.c index 5c6586aa99..52b1bafb79 100644 --- a/racket/src/rktio/rktio_main.c +++ b/racket/src/rktio/rktio_main.c @@ -29,6 +29,7 @@ void rktio_destroy(rktio_t *rktio) rktio_process_deinit(rktio); rktio_free_ghbn(rktio); rktio_free_global_poll_set(rktio); + rktio_stop_fs_change(rktio); free(rktio); } diff --git a/racket/src/rktio/rktio_network.c b/racket/src/rktio/rktio_network.c index abe7dfea66..e924977667 100644 --- a/racket/src/rktio/rktio_network.c +++ b/racket/src/rktio/rktio_network.c @@ -26,15 +26,8 @@ typedef intptr_t rktio_socket_t; # define INVALID_SOCKET (-1) -static void reliably_close(intptr_t s) { - int cr; - do { - cr = close(s); - } while ((cr == -1) && (errno == EINTR)); -} - static void closesocket(rktio_socket_t s) { - reliably_close(s); + rktio_reliably_close(s); } typedef struct sockaddr_in rktio_unspec_address; @@ -430,7 +423,7 @@ static intptr_t getaddrinfo_in_thread(void *_data) do { err = write(lookup->done_fd[1], &v, sizeof(v)); } while ((err == -1) && (errno == EINTR)); - reliably_close(lookup->done_fd[1]); + rktio_reliably_close(lookup->done_fd[1]); } # endif @@ -438,7 +431,7 @@ static intptr_t getaddrinfo_in_thread(void *_data) # ifdef RKTIO_SYSTEM_WINDOWS CloseHandle(data->ready_sema); # else - reliably_close(lookup->done_fd[0]); + rktio_reliably_close(lookup->done_fd[0]); # endif free_lookup(lookup); } @@ -582,7 +575,7 @@ int rktio_poll_addrinfo_lookup_ready(rktio_t *rktio, rktio_addrinfo_lookup_t *lo cr = read(lookup->done_fd[0], &v, sizeof(long)); } while ((cr == -1) && (errno == EINTR)); if (cr > 0) { - reliably_close(lookup->done_fd[0]); + rktio_reliably_close(lookup->done_fd[0]); done = 1; } } @@ -633,7 +626,7 @@ void rktio_addrinfo_lookup_stop(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup) # ifdef RKTIO_SYSTEM_WINDOWS CloseHandle(lookup->done_sema); # else - reliably_close(lookup->done_fd[0]); + rktio_reliably_close(lookup->done_fd[0]); # endif free_lookup(lookup); } diff --git a/racket/src/rktio/rktio_private.h b/racket/src/rktio/rktio_private.h index 3e7730bbd1..3ff3625fda 100644 --- a/racket/src/rktio/rktio_private.h +++ b/racket/src/rktio/rktio_private.h @@ -82,6 +82,10 @@ struct rktio_t { #ifdef RKTIO_SYSTEM_WINDOWS uintptr_t process_children_msecs; #endif + +#ifdef HAVE_INOTIFY_SYSCALL + struct rin_inotify_state_t *inotify_server; +#endif }; /*========================================================================*/ @@ -214,4 +218,14 @@ void rktio_get_windows_error(rktio_t *rktio); # define RKTIO_NONBLOCKING FNDELAY #endif +#ifndef RKTIO_BINARY +# define RKTIO_BINARY 0 +#endif + +#ifdef RKTIO_SYSTEM_UNIX +void rktio_reliably_close(intptr_t s); +#endif + void *rktio_envvars_to_block(rktio_t *rktio, rktio_envvars_t *envvars); + +void rktio_stop_fs_change(rktio_t *rktio); diff --git a/racket/src/rktio/rktio_process.c b/racket/src/rktio/rktio_process.c index b3d5949370..f40e533982 100644 --- a/racket/src/rktio/rktio_process.c +++ b/racket/src/rktio/rktio_process.c @@ -1221,13 +1221,6 @@ static void CloseFileHandleForSubprocess(intptr_t *hs, int pos) #ifdef RKTIO_SYSTEM_UNIX # define RKTIO_COPY_FOR_SUBPROCESS(array, pos) /* empty */ # define RKTIO_CLOSE_SUBPROCESS_COPY(array, pos) /* empty */ - -static void reliably_close(intptr_t s) { - int cr; - do { - cr = close(s); - } while ((cr == -1) && (errno == EINTR)); -} #endif /*========================================================================*/ @@ -1430,21 +1423,21 @@ rktio_process_result_t *rktio_process(rktio_t *rktio, case -1: /* Close all created descriptors */ if (!stdin_fd) { - reliably_close(to_subprocess[0]); - reliably_close(to_subprocess[1]); + rktio_reliably_close(to_subprocess[0]); + rktio_reliably_close(to_subprocess[1]); } else { RKTIO_CLOSE_SUBPROCESS_COPY(to_subprocess, 0); } if (!stdout_fd) { - reliably_close(from_subprocess[0]); - reliably_close(from_subprocess[1]); + rktio_reliably_close(from_subprocess[0]); + rktio_reliably_close(from_subprocess[1]); } else { RKTIO_CLOSE_SUBPROCESS_COPY(from_subprocess, 1); } if (!stderr_fd) { if (!stderr_is_stdout) { - reliably_close(err_subprocess[0]); - reliably_close(err_subprocess[1]); + rktio_reliably_close(err_subprocess[0]); + rktio_reliably_close(err_subprocess[1]); } } else { RKTIO_CLOSE_SUBPROCESS_COPY(err_subprocess, 1); @@ -1467,17 +1460,17 @@ rktio_process_result_t *rktio_process(rktio_t *rktio, /* Close unwanted descriptors */ if (!stdin_fd) { - reliably_close(to_subprocess[0]); - reliably_close(to_subprocess[1]); + rktio_reliably_close(to_subprocess[0]); + rktio_reliably_close(to_subprocess[1]); } if (!stdout_fd) { - reliably_close(from_subprocess[0]); - reliably_close(from_subprocess[1]); + rktio_reliably_close(from_subprocess[0]); + rktio_reliably_close(from_subprocess[1]); } if (!stderr_fd) { if (!stderr_is_stdout) { - reliably_close(err_subprocess[0]); - reliably_close(err_subprocess[1]); + rktio_reliably_close(err_subprocess[0]); + rktio_reliably_close(err_subprocess[1]); } } @@ -1531,18 +1524,18 @@ rktio_process_result_t *rktio_process(rktio_t *rktio, free(env); if (!stdin_fd) { - reliably_close(to_subprocess[0]); + rktio_reliably_close(to_subprocess[0]); } else { RKTIO_CLOSE_SUBPROCESS_COPY(to_subprocess, 0); } if (!stdout_fd) { - reliably_close(from_subprocess[1]); + rktio_reliably_close(from_subprocess[1]); } else { RKTIO_CLOSE_SUBPROCESS_COPY(from_subprocess, 1); } if (!stderr_fd) { if (!stderr_is_stdout) - reliably_close(err_subprocess[1]); + rktio_reliably_close(err_subprocess[1]); } else { RKTIO_CLOSE_SUBPROCESS_COPY(err_subprocess, 1); }