rktio: add filesystem-change events
This commit is contained in:
parent
19776f6bb9
commit
2187e77e65
|
@ -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
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -12,10 +12,6 @@
|
|||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifndef RKTIO_BINARY
|
||||
# define RKTIO_BINARY 0
|
||||
#endif
|
||||
|
||||
/*************************************************************/
|
||||
/* opening a file fd */
|
||||
/*************************************************************/
|
||||
|
|
522
racket/src/rktio/rktio_fs_change.c
Normal file
522
racket/src/rktio/rktio_fs_change.c
Normal file
|
@ -0,0 +1,522 @@
|
|||
#include "rktio.h"
|
||||
#include "rktio_private.h"
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#if defined(HAVE_KQUEUE_SYSCALL)
|
||||
# include <fcntl.h>
|
||||
#endif
|
||||
#if defined(HAVE_INOTIFY_SYSCALL)
|
||||
# include <poll.h>
|
||||
# include <sys/inotify.h>
|
||||
#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
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user