From 0a46f7ec23a924f4e53874ce32471209b2b70686 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Sat, 23 Feb 2019 01:35:58 -0500 Subject: [PATCH] [core] some fdevent code streamlining isolate fde_ndx to fdevent framework internals --- src/fdevent.c | 216 ++++++++++++++-------------------- src/fdevent.h | 6 +- src/fdevent_freebsd_kqueue.c | 157 +++++------------------- src/fdevent_impl.h | 12 +- src/fdevent_libev.c | 72 ++++-------- src/fdevent_linux_sysepoll.c | 90 +++----------- src/fdevent_poll.c | 83 ++++--------- src/fdevent_select.c | 62 +++------- src/fdevent_solaris_devpoll.c | 90 +++----------- src/fdevent_solaris_port.c | 113 +++++------------- 10 files changed, 264 insertions(+), 637 deletions(-) diff --git a/src/fdevent.c b/src/fdevent.c index d20e6fd3..be7db2b7 100644 --- a/src/fdevent.c +++ b/src/fdevent.c @@ -196,66 +196,51 @@ fdevents *fdevent_init(server *srv) { ev->maxfds = maxfds; switch(type) { + #ifdef FDEVENT_USE_POLL case FDEVENT_HANDLER_POLL: - if (0 != fdevent_poll_init(ev)) { - log_error_write(srv, __FILE__, __LINE__, "S", - "event-handler poll failed"); - goto error; - } - return ev; + if (0 == fdevent_poll_init(ev)) return ev; + break; + #endif + #ifdef FDEVENT_USE_SELECT case FDEVENT_HANDLER_SELECT: - if (0 != fdevent_select_init(ev)) { - log_error_write(srv, __FILE__, __LINE__, "S", - "event-handler select failed"); - goto error; - } - return ev; + if (0 == fdevent_select_init(ev)) return ev; + break; + #endif + #ifdef FDEVENT_USE_LINUX_EPOLL case FDEVENT_HANDLER_LINUX_SYSEPOLL: - if (0 != fdevent_linux_sysepoll_init(ev)) { - log_error_write(srv, __FILE__, __LINE__, "S", - "event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\""); - goto error; - } - return ev; + if (0 == fdevent_linux_sysepoll_init(ev)) return ev; + break; + #endif + #ifdef FDEVENT_USE_SOLARIS_DEVPOLL case FDEVENT_HANDLER_SOLARIS_DEVPOLL: - if (0 != fdevent_solaris_devpoll_init(ev)) { - log_error_write(srv, __FILE__, __LINE__, "S", - "event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\""); - goto error; - } - return ev; + if (0 == fdevent_solaris_devpoll_init(ev)) return ev; + break; + #endif + #ifdef FDEVENT_USE_SOLARIS_PORT case FDEVENT_HANDLER_SOLARIS_PORT: - if (0 != fdevent_solaris_port_init(ev)) { - log_error_write(srv, __FILE__, __LINE__, "S", - "event-handler solaris-eventports failed, try to set server.event-handler = \"poll\" or \"select\""); - goto error; - } - return ev; + if (0 == fdevent_solaris_port_init(ev)) return ev; + break; + #endif + #ifdef FDEVENT_USE_FREEBSD_KQUEUE case FDEVENT_HANDLER_FREEBSD_KQUEUE: - if (0 != fdevent_freebsd_kqueue_init(ev)) { - log_error_write(srv, __FILE__, __LINE__, "S", - "event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\""); - goto error; - } - return ev; + if (0 == fdevent_freebsd_kqueue_init(ev)) return ev; + break; + #endif + #ifdef FDEVENT_USE_LIBEV case FDEVENT_HANDLER_LIBEV: - if (0 != fdevent_libev_init(ev)) { - log_error_write(srv, __FILE__, __LINE__, "S", - "event-handler libev failed, try to set server.event-handler = \"poll\" or \"select\""); - goto error; - } - return ev; + if (0 == fdevent_libev_init(ev)) return ev; + break; + #endif case FDEVENT_HANDLER_UNSET: default: break; } -error: free(ev->fdarray); free(ev); - log_error_write(srv, __FILE__, __LINE__, "S", - "event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\""); + log_error_write(srv, __FILE__, __LINE__, "sBS", + "event-handler failed:", srv->srvconf.event_handler, "; try to set server.event-handler = \"poll\" or \"select\""); return NULL; } @@ -277,59 +262,44 @@ void fdevent_free(fdevents *ev) { } int fdevent_reset(fdevents *ev) { - if (ev->reset) return ev->reset(ev); - - return 0; + int rc = (NULL != ev->reset) ? ev->reset(ev) : 0; + if (-1 == rc) { + log_error_write(ev->srv, __FILE__, __LINE__, "sBS", + "event-handler failed:", ev->srv->srvconf.event_handler, "; try to set server.event-handler = \"poll\" or \"select\""); + } + return rc; } static fdnode *fdnode_init(void) { - fdnode *fdn; - - fdn = calloc(1, sizeof(*fdn)); - force_assert(NULL != fdn); - fdn->fd = -1; - return fdn; + return calloc(1, sizeof(fdnode)); } static void fdnode_free(fdnode *fdn) { free(fdn); } -int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) { - fdnode *fdn; - - fdn = fdnode_init(); +void fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) { + fdnode *fdn = ev->fdarray[fd] = fdnode_init(); + force_assert(NULL != fdn); fdn->handler = handler; fdn->fd = fd; fdn->ctx = ctx; fdn->events = 0; + fdn->fde_ndx = -1; #ifdef FDEVENT_USE_LIBEV fdn->handler_ctx = NULL; #endif - - ev->fdarray[fd] = fdn; - - return 0; } -int fdevent_unregister(fdevents *ev, int fd) { - fdnode *fdn; - - if (!ev) return 0; - fdn = ev->fdarray[fd]; - if ((uintptr_t)fdn & 0x3) return 0; /*(should not happen)*/ - - fdnode_free(fdn); - +void fdevent_unregister(fdevents *ev, int fd) { + fdnode *fdn = ev->fdarray[fd]; + if ((uintptr_t)fdn & 0x3) return; /*(should not happen)*/ ev->fdarray[fd] = NULL; - - return 0; + fdnode_free(fdn); } void fdevent_sched_close(fdevents *ev, int fd, int issock) { - fdnode *fdn; - if (!ev) return; - fdn = ev->fdarray[fd]; + fdnode *fdn = ev->fdarray[fd]; if ((uintptr_t)fdn & 0x3) return; ev->fdarray[fd] = (fdnode *)((uintptr_t)fdn | (issock ? 0x1 : 0x2)); fdn->ctx = ev->pendclose; @@ -376,72 +346,66 @@ int fdevent_event_get_interest(const fdevents *ev, int fd) { return fd >= 0 ? ev->fdarray[fd]->events : 0; } -void fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) { - if (-1 == fd) return; - if ((uintptr_t)ev->fdarray[fd] & 0x3) return; - - if (ev->event_del) *fde_ndx = ev->event_del(ev, *fde_ndx, fd); - ev->fdarray[fd]->events = 0; +static void fdevent_fdnode_event_del(fdevents *ev, fdnode *fdn) { + if (-1 == fdn->fde_ndx) return; + if (0 == ev->event_del(ev, fdn)) { + fdn->fde_ndx = -1; + fdn->events = 0; + } + else { + log_error_write(ev->srv, __FILE__, __LINE__, "SS", + "fdevent event_del failed: ", strerror(errno)); + } } -void fdevent_event_set(fdevents *ev, int *fde_ndx, int fd, int events) { - if (-1 == fd) return; - - /*(Note: skips registering with kernel if initial events is 0, - * so caller should pass non-zero events for initial registration. - * If never registered due to never being called with non-zero events, - * then FDEVENT_HUP or FDEVENT_ERR will never be returned.) */ - if (ev->fdarray[fd]->events == events) return;/*(no change; nothing to do)*/ +static void fdevent_fdnode_event_set(fdevents *ev, fdnode *fdn, int events) { + /*(Note: skips registering with kernel if initial events is 0, + * so caller should pass non-zero events for initial registration. + * If never registered due to never being called with non-zero events, + * then FDEVENT_HUP or FDEVENT_ERR will never be returned.) */ + if (fdn->events == events) return;/*(no change; nothing to do)*/ - if (ev->event_set) *fde_ndx = ev->event_set(ev, *fde_ndx, fd, events); - ev->fdarray[fd]->events = events; + if (0 == ev->event_set(ev, fdn, events)) + fdn->events = events; + else + log_error_write(ev->srv, __FILE__, __LINE__, "SS", + "fdevent event_set failed: ", strerror(errno)); } -void fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int event) { - int events; - if (-1 == fd) return; +void fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) { + UNUSED(fde_ndx); + if (-1 != fd) { + fdnode *fdn = ev->fdarray[fd]; + if ((uintptr_t)fdn & 0x3) return; + fdevent_fdnode_event_del(ev, fdn); + } +} - events = ev->fdarray[fd]->events; - if ((events & event) == event) return; /*(no change; nothing to do)*/ +void fdevent_event_set(fdevents *ev, int *fde_ndx, int fd, int events) { + UNUSED(fde_ndx); + if (-1 != fd) fdevent_fdnode_event_set(ev, ev->fdarray[fd], events); +} - events |= event; - if (ev->event_set) *fde_ndx = ev->event_set(ev, *fde_ndx, fd, events); - ev->fdarray[fd]->events = events; +void fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int event) { + UNUSED(fde_ndx); + if (-1 != fd) { + fdnode *fdn = ev->fdarray[fd]; + fdevent_fdnode_event_set(ev, fdn, (fdn->events | event)); + } } void fdevent_event_clr(fdevents *ev, int *fde_ndx, int fd, int event) { - int events; - if (-1 == fd) return; - - events = ev->fdarray[fd]->events; - if (!(events & event)) return; /*(no change; nothing to do)*/ - - events &= ~event; - if (ev->event_set) *fde_ndx = ev->event_set(ev, *fde_ndx, fd, events); - ev->fdarray[fd]->events = events; + UNUSED(fde_ndx); + if (-1 != fd) { + fdnode *fdn = ev->fdarray[fd]; + fdevent_fdnode_event_set(ev, fdn, (fdn->events & ~event)); + } } int fdevent_poll(fdevents *ev, int timeout_ms) { - if (ev->poll == NULL) SEGFAULT(); return ev->poll(ev, timeout_ms); } -fdevent_handler fdevent_get_handler(fdevents *ev, int fd) { - if (ev->fdarray[fd] == NULL) SEGFAULT(); - if ((uintptr_t)ev->fdarray[fd] & 0x3) return NULL; - if (ev->fdarray[fd]->fd != fd) SEGFAULT(); - - return ev->fdarray[fd]->handler; -} - -void * fdevent_get_context(fdevents *ev, int fd) { - if (ev->fdarray[fd] == NULL) SEGFAULT(); - if ((uintptr_t)ev->fdarray[fd] & 0x3) return NULL; - if (ev->fdarray[fd]->fd != fd) SEGFAULT(); - - return ev->fdarray[fd]->ctx; -} - void fdevent_setfd_cloexec(int fd) { #ifdef FD_CLOEXEC if (fd < 0) return; diff --git a/src/fdevent.h b/src/fdevent.h index 715f0ae9..c306324f 100644 --- a/src/fdevent.h +++ b/src/fdevent.h @@ -55,13 +55,11 @@ void fdevent_event_set(fdevents *ev, int *fde_ndx, int fd, int events); /* event void fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int event); /* events can be FDEVENT_IN or FDEVENT_OUT */ void fdevent_event_clr(fdevents *ev, int *fde_ndx, int fd, int event); /* events can be FDEVENT_IN or FDEVENT_OUT */ void fdevent_event_del(fdevents *ev, int *fde_ndx, int fd); -fdevent_handler fdevent_get_handler(fdevents *ev, int fd); -void * fdevent_get_context(fdevents *ev, int fd); int fdevent_poll(fdevents *ev, int timeout_ms); -int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx); -int fdevent_unregister(fdevents *ev, int fd); +void fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx); +void fdevent_unregister(fdevents *ev, int fd); void fdevent_sched_close(fdevents *ev, int fd, int issock); void fdevent_sched_run(struct server *srv, fdevents *ev); diff --git a/src/fdevent_freebsd_kqueue.c b/src/fdevent_freebsd_kqueue.c index db122c10..cef543bc 100644 --- a/src/fdevent_freebsd_kqueue.c +++ b/src/fdevent_freebsd_kqueue.c @@ -3,34 +3,29 @@ #include "fdevent_impl.h" #include "fdevent.h" #include "buffer.h" -#include "log.h" - -#include #include #include #include -#include #include #ifdef FDEVENT_USE_FREEBSD_KQUEUE + # include # include +__attribute_cold__ static void fdevent_freebsd_kqueue_free(fdevents *ev) { close(ev->kq_fd); free(ev->kq_results); } -static int fdevent_freebsd_kqueue_event_del(fdevents *ev, int fde_ndx, int fd) { - int ret, n = 0; +static int fdevent_freebsd_kqueue_event_del(fdevents *ev, fdnode *fdn) { struct kevent kev[2]; - struct timespec ts; - int oevents; - - if (fde_ndx < 0) return -1; - - oevents = ev->fdarray[fd]->events; + struct timespec ts = {0, 0}; + int fd = fdn->fd; + int n = 0; + int oevents = fdn->events; if (oevents & FDEVENT_IN) { EV_SET(&kev[n], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); @@ -41,38 +36,18 @@ static int fdevent_freebsd_kqueue_event_del(fdevents *ev, int fde_ndx, int fd) { n++; } - if (0 == n) return -1; - - ts.tv_sec = 0; - ts.tv_nsec = 0; - - ret = kevent(ev->kq_fd, - kev, n, - NULL, 0, - &ts); - - if (ret == -1) { - log_error_write(ev->srv, __FILE__, __LINE__, "SS", - "kqueue event delete failed: ", strerror(errno)); - - return -1; - } - - return -1; + return (0 != n) ? kevent(ev->kq_fd, kev, n, NULL, 0, &ts) : 0; } -static int fdevent_freebsd_kqueue_event_set(fdevents *ev, int fde_ndx, int fd, int events) { - int ret, n = 0; +static int fdevent_freebsd_kqueue_event_set(fdevents *ev, fdnode *fdn, int events) { struct kevent kev[2]; - struct timespec ts; - int oevents = ev->fdarray[fd]->events; + struct timespec ts = {0, 0}; + int fd = fdn->fde_ndx = fdn->fd; + int n = 0; + int oevents = fdn->events; int addevents = events & ~oevents; int delevents = ~events & oevents; - UNUSED(fde_ndx); - - if (events == oevents) return fd; - if (addevents & FDEVENT_IN) { EV_SET(&kev[n], fd, EVFILT_READ, EV_ADD, 0, 0, NULL); n++; @@ -88,50 +63,7 @@ static int fdevent_freebsd_kqueue_event_set(fdevents *ev, int fde_ndx, int fd, i n++; } - if (0 == n) return fd; - - ts.tv_sec = 0; - ts.tv_nsec = 0; - - ret = kevent(ev->kq_fd, - kev, n, - NULL, 0, - &ts); - - if (ret == -1) { - log_error_write(ev->srv, __FILE__, __LINE__, "SS", - "kqueue event set failed: ", strerror(errno)); - - return -1; - } - - return fd; -} - -static int fdevent_freebsd_kqueue_event_get_revent(const fdevents *ev, size_t ndx) { - int events = 0; - int filt = ev->kq_results[ndx].filter; - int e = ev->kq_results[ndx].flags; - - if (filt == EVFILT_READ) { - events |= FDEVENT_IN; - } else if (filt == EVFILT_WRITE) { - events |= FDEVENT_OUT; - } - - if (e & EV_EOF) { - if (filt == EVFILT_READ) { - events |= FDEVENT_RDHUP; - } else { - events |= FDEVENT_HUP; - } - } - - if (e & EV_ERROR) { - events |= FDEVENT_ERR; - } - - return events; + return (0 != n) ? kevent(ev->kq_fd, kev, n, NULL, 0, &ts) : 0; } static int fdevent_freebsd_kqueue_poll(fdevents * const ev, int timeout_ms) { @@ -146,64 +78,37 @@ static int fdevent_freebsd_kqueue_poll(fdevents * const ev, int timeout_ms) { for (int i = 0; i < n; ++i) { fdnode * const fdn = ev->fdarray[ev->kq_results[i].ident]; + int filt = ev->kq_results[i].filter; + int e = ev->kq_results[i].flags; if (0 == ((uintptr_t)fdn & 0x3)) { - int revents = fdevent_freebsd_kqueue_event_get_revent(ev, i); + int revents = (filt == EVFILT_READ) ? FDEVENT_IN : FDEVENT_OUT; + if (e & EV_EOF) + revents |= (filt == EVFILT_READ ? FDEVENT_RDHUP : FDEVENT_HUP); + if (e & EV_ERROR) + revents |= FDEVENT_ERR; (*fdn->handler)(srv, fdn->ctx, revents); } } return n; } +__attribute_cold__ static int fdevent_freebsd_kqueue_reset(fdevents *ev) { - if (-1 == (ev->kq_fd = kqueue())) { - log_error_write(ev->srv, __FILE__, __LINE__, "SSS", - "kqueue failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\""); - - return -1; - } - - return 0; + return (-1 != (ev->kq_fd = kqueue())) ? 0 : -1; } - +__attribute_cold__ int fdevent_freebsd_kqueue_init(fdevents *ev) { - ev->type = FDEVENT_HANDLER_FREEBSD_KQUEUE; -#define SET(x) \ - ev->x = fdevent_freebsd_kqueue_##x; - - SET(free); - SET(poll); - SET(reset); - - SET(event_del); - SET(event_set); - - ev->kq_fd = -1; - + ev->type = FDEVENT_HANDLER_FREEBSD_KQUEUE; + ev->event_set = fdevent_freebsd_kqueue_event_set; + ev->event_del = fdevent_freebsd_kqueue_event_del; + ev->poll = fdevent_freebsd_kqueue_poll; + ev->reset = fdevent_freebsd_kqueue_reset; + ev->free = fdevent_freebsd_kqueue_free; + ev->kq_fd = -1; ev->kq_results = calloc(ev->maxfds, sizeof(*ev->kq_results)); force_assert(NULL != ev->kq_results); - - /* check that kqueue works */ - - if (-1 == (ev->kq_fd = kqueue())) { - log_error_write(ev->srv, __FILE__, __LINE__, "SSS", - "kqueue failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\""); - - return -1; - } - - close(ev->kq_fd); - ev->kq_fd = -1; - return 0; } -#else -int fdevent_freebsd_kqueue_init(fdevents *ev) { - UNUSED(ev); - log_error_write(ev->srv, __FILE__, __LINE__, "S", - "kqueue not available, try to set server.event-handler = \"poll\" or \"select\""); - - return -1; -} #endif diff --git a/src/fdevent_impl.h b/src/fdevent_impl.h index ee0e052f..f1b2a054 100644 --- a/src/fdevent_impl.h +++ b/src/fdevent_impl.h @@ -65,6 +65,7 @@ typedef struct _fdnode { void *ctx; int fd; int events; + int fde_ndx; #ifdef FDEVENT_USE_LIBEV void *handler_ctx; #endif @@ -88,8 +89,8 @@ struct fdevents { fdnode **fdarray; fdnode *pendclose; - int (*event_set)(struct fdevents *ev, int fde_ndx, int fd, int events); - int (*event_del)(struct fdevents *ev, int fde_ndx, int fd); + int (*event_set)(struct fdevents *ev, fdnode *fdn, int events); + int (*event_del)(struct fdevents *ev, fdnode *fdn); int (*poll)(struct fdevents *ev, int timeout_ms); struct server *srv; @@ -138,12 +139,19 @@ struct fdevents { fdevent_handler_t type; }; +__attribute_cold__ int fdevent_select_init(struct fdevents *ev); +__attribute_cold__ int fdevent_poll_init(struct fdevents *ev); +__attribute_cold__ int fdevent_linux_sysepoll_init(struct fdevents *ev); +__attribute_cold__ int fdevent_solaris_devpoll_init(struct fdevents *ev); +__attribute_cold__ int fdevent_solaris_port_init(struct fdevents *ev); +__attribute_cold__ int fdevent_freebsd_kqueue_init(struct fdevents *ev); +__attribute_cold__ int fdevent_libev_init(struct fdevents *ev); #endif diff --git a/src/fdevent_libev.c b/src/fdevent_libev.c index 666d3ecd..6d9155b4 100644 --- a/src/fdevent_libev.c +++ b/src/fdevent_libev.c @@ -5,7 +5,6 @@ #include "fdevent_impl.h" #include "fdevent.h" #include "buffer.h" -#include "log.h" #ifdef FDEVENT_USE_LIBEV @@ -13,46 +12,38 @@ static void io_watcher_cb(struct ev_loop *loop, ev_io *w, int revents) { fdevents *ev = w->data; - fdevent_handler handler = fdevent_get_handler(ev, w->fd); - void *context = fdevent_get_context(ev, w->fd); + fdnode *fdn = ev->fdarray[w->fd]; int r = 0; UNUSED(loop); - if (NULL == handler) return; if (revents & EV_READ) r |= FDEVENT_IN; if (revents & EV_WRITE) r |= FDEVENT_OUT; if (revents & EV_ERROR) r |= FDEVENT_ERR; - (*handler)(ev->srv, context, r); + if (0 == ((uintptr_t)fdn & 0x3)) { + (*fdn->handler)(ev->srv, fdn->ctx, r); + } } +__attribute_cold__ static void fdevent_libev_free(fdevents *ev) { UNUSED(ev); } -static int fdevent_libev_event_del(fdevents *ev, int fde_ndx, int fd) { - fdnode *fdn; - ev_io *watcher; - - if (-1 == fde_ndx) return -1; - - fdn = ev->fdarray[fd]; - watcher = fdn->handler_ctx; - - if (!watcher) return -1; +static int fdevent_libev_event_del(fdevents *ev, fdnode *fdn) { + ev_io *watcher = fdn->handler_ctx; + if (!watcher) return 0; + fdn->handler_ctx = NULL; ev_io_stop(ev->libev_loop, watcher); free(watcher); - fdn->handler_ctx = NULL; - return -1; + return 0; } -static int fdevent_libev_event_set(fdevents *ev, int fde_ndx, int fd, int events) { - fdnode *fdn = ev->fdarray[fd]; +static int fdevent_libev_event_set(fdevents *ev, fdnode *fdn, int events) { ev_io *watcher = fdn->handler_ctx; int ev_events = 0; - UNUSED(fde_ndx); if (events & FDEVENT_IN) ev_events |= EV_READ; if (events & FDEVENT_OUT) ev_events |= EV_WRITE; @@ -60,8 +51,9 @@ static int fdevent_libev_event_set(fdevents *ev, int fde_ndx, int fd, int events if (!watcher) { fdn->handler_ctx = watcher = calloc(1, sizeof(ev_io)); force_assert(watcher); + fdn->fde_ndx = fdn->fd; - ev_io_init(watcher, io_watcher_cb, fd, ev_events); + ev_io_init(watcher, io_watcher_cb, fdn->fd, ev_events); watcher->data = ev; ev_io_start(ev->libev_loop, watcher); } else { @@ -72,7 +64,7 @@ static int fdevent_libev_event_set(fdevents *ev, int fde_ndx, int fd, int events } } - return fd; + return 0; } static void timeout_watcher_cb(struct ev_loop *loop, ev_timer *w, int revents) { @@ -92,48 +84,30 @@ static int fdevent_libev_poll(fdevents *ev, int timeout_ms) { return 0; } +__attribute_cold__ static int fdevent_libev_reset(fdevents *ev) { UNUSED(ev); - ev_default_fork(); - return 0; } +__attribute_cold__ int fdevent_libev_init(fdevents *ev) { struct ev_timer * const timer = &timeout_watcher; memset(timer, 0, sizeof(*timer)); - ev->type = FDEVENT_HANDLER_LIBEV; -#define SET(x) \ - ev->x = fdevent_libev_##x; - - SET(free); - SET(poll); - SET(reset); - - SET(event_del); - SET(event_set); + ev->type = FDEVENT_HANDLER_LIBEV; + ev->event_set = fdevent_libev_event_set; + ev->event_del = fdevent_libev_event_del; + ev->poll = fdevent_libev_poll; + ev->reset = fdevent_libev_reset; + ev->free = fdevent_libev_free; - if (NULL == (ev->libev_loop = ev_default_loop(0))) { - log_error_write(ev->srv, __FILE__, __LINE__, "S", - "ev_default_loop failed , try to set server.event-handler = \"poll\" or \"select\""); - - return -1; - } + if (NULL == (ev->libev_loop = ev_default_loop(0))) return -1; ev_timer_init(timer, timeout_watcher_cb, 0.0, 1.0); return 0; } -#else -int fdevent_libev_init(fdevents *ev) { - UNUSED(ev); - - log_error_write(ev->srv, __FILE__, __LINE__, "S", - "libev not supported, try to set server.event-handler = \"poll\" or \"select\""); - - return -1; -} #endif diff --git a/src/fdevent_linux_sysepoll.c b/src/fdevent_linux_sysepoll.c index 4b4db40d..24e19201 100644 --- a/src/fdevent_linux_sysepoll.c +++ b/src/fdevent_linux_sysepoll.c @@ -3,76 +3,40 @@ #include "fdevent_impl.h" #include "fdevent.h" #include "buffer.h" -#include "log.h" - -#include #include #include #include -#include #ifdef FDEVENT_USE_LINUX_EPOLL # include -#ifndef EPOLLRDHUP -#define EPOLLRDHUP 0 -#endif - +__attribute_cold__ static void fdevent_linux_sysepoll_free(fdevents *ev) { close(ev->epoll_fd); free(ev->epoll_events); } -static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) { - if (fde_ndx < 0) return -1; - - if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, NULL)) { - log_error_write(ev->srv, __FILE__, __LINE__, "SSS", - "epoll_ctl failed: ", strerror(errno), ", dying"); - - SEGFAULT(); - - return 0; - } - - return -1; +static int fdevent_linux_sysepoll_event_del(fdevents *ev, fdnode *fdn) { + return epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fdn->fd, NULL); } -static int fdevent_linux_sysepoll_event_set(fdevents *ev, int fde_ndx, int fd, int events) { - struct epoll_event ep; - int add = (-1 == fde_ndx); - - /** - * - * with EPOLLET we don't get a FDEVENT_HUP - * if the close is delay after everything has - * sent. - * - */ - - ep.events = events | EPOLLERR | EPOLLHUP /* | EPOLLET */; - ep.data.fd = fd; - - if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) { - log_error_write(ev->srv, __FILE__, __LINE__, "SSS", - "epoll_ctl failed: ", strerror(errno), ", dying"); - - SEGFAULT(); - - return 0; - } - - return fd; +static int fdevent_linux_sysepoll_event_set(fdevents *ev, fdnode *fdn, int events) { + int op = (-1 == fdn->fde_ndx) ? EPOLL_CTL_ADD : EPOLL_CTL_MOD; + int fd = fdn->fde_ndx = fdn->fd; + struct epoll_event ep; + ep.events = events | EPOLLERR | EPOLLHUP; + ep.data.fd = fd; + return epoll_ctl(ev->epoll_fd, op, fd, &ep); } static int fdevent_linux_sysepoll_poll(fdevents * const ev, int timeout_ms) { int n = epoll_wait(ev->epoll_fd, ev->epoll_events, ev->maxfds, timeout_ms); server * const srv = ev->srv; for (int i = 0; i < n; ++i) { - int revents = ev->epoll_events[i].events; fdnode * const fdn = ev->fdarray[ev->epoll_events[i].data.fd]; + int revents = ev->epoll_events[i].events; if (0 == ((uintptr_t)fdn & 0x3)) { (*fdn->handler)(srv, fdn->ctx, revents); } @@ -80,31 +44,24 @@ static int fdevent_linux_sysepoll_poll(fdevents * const ev, int timeout_ms) { return n; } +__attribute_cold__ int fdevent_linux_sysepoll_init(fdevents *ev) { - ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL; force_assert(EPOLLIN == FDEVENT_IN); force_assert(EPOLLPRI == FDEVENT_PRI); force_assert(EPOLLOUT == FDEVENT_OUT); force_assert(EPOLLERR == FDEVENT_ERR); force_assert(EPOLLHUP == FDEVENT_HUP); - #if 0 != EPOLLRDHUP + #ifdef EPOLLRDHUP force_assert(EPOLLRDHUP == FDEVENT_RDHUP); #endif -#define SET(x) \ - ev->x = fdevent_linux_sysepoll_##x; - - SET(free); - SET(poll); - SET(event_del); - SET(event_set); + ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL; + ev->event_set = fdevent_linux_sysepoll_event_set; + ev->event_del = fdevent_linux_sysepoll_event_del; + ev->poll = fdevent_linux_sysepoll_poll; + ev->free = fdevent_linux_sysepoll_free; - if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) { - log_error_write(ev->srv, __FILE__, __LINE__, "SSS", - "epoll_create failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\""); - - return -1; - } + if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) return -1; fdevent_setfd_cloexec(ev->epoll_fd); @@ -114,13 +71,4 @@ int fdevent_linux_sysepoll_init(fdevents *ev) { return 0; } -#else -int fdevent_linux_sysepoll_init(fdevents *ev) { - UNUSED(ev); - - log_error_write(ev->srv, __FILE__, __LINE__, "S", - "linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\""); - - return -1; -} #endif diff --git a/src/fdevent_poll.c b/src/fdevent_poll.c index 41e53af6..b1b34550 100644 --- a/src/fdevent_poll.c +++ b/src/fdevent_poll.c @@ -3,9 +3,6 @@ #include "fdevent_impl.h" #include "fdevent.h" #include "buffer.h" -#include "log.h" - -#include #include #include @@ -20,26 +17,16 @@ # include # endif -#ifndef POLLRDHUP -#define POLLRDHUP 0 -#endif - +__attribute_cold__ static void fdevent_poll_free(fdevents *ev) { free(ev->pollfds); if (ev->unused.ptr) free(ev->unused.ptr); } -static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) { - if (fde_ndx < 0) return -1; - - if ((size_t)fde_ndx >= ev->used) { - log_error_write(ev->srv, __FILE__, __LINE__, "SdD", - "del! out of range ", fde_ndx, (int) ev->used); - SEGFAULT(); - } - - if (ev->pollfds[fde_ndx].fd == fd) { - size_t k = fde_ndx; +static int fdevent_poll_event_del(fdevents *ev, fdnode *fdn) { + int fd = fdn->fd; + int k = fdn->fde_ndx; + if ((size_t)k >= ev->used || ev->pollfds[k].fd != fd) return (errno = EINVAL, -1); ev->pollfds[k].fd = -1; /* ev->pollfds[k].events = 0; */ @@ -52,28 +39,18 @@ static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) { } ev->unused.ptr[ev->unused.used++] = k; - } else { - log_error_write(ev->srv, __FILE__, __LINE__, "SdD", - "del! ", ev->pollfds[fde_ndx].fd, fd); - SEGFAULT(); - } - - return -1; + return 0; } -static int fdevent_poll_event_set(fdevents *ev, int fde_ndx, int fd, int events) { - int k; - - if (fde_ndx != -1) { - if (ev->pollfds[fde_ndx].fd == fd) { - ev->pollfds[fde_ndx].events = events; +static int fdevent_poll_event_set(fdevents *ev, fdnode *fdn, int events) { + int fd = fdn->fd; + int k = fdn->fde_ndx; - return fde_ndx; - } - log_error_write(ev->srv, __FILE__, __LINE__, "SdD", - "set: ", fde_ndx, ev->pollfds[fde_ndx].fd); - SEGFAULT(); + if (k >= 0) { + if ((size_t)k >= ev->used || ev->pollfds[k].fd != fd) return (errno = EINVAL, -1); + ev->pollfds[k].events = events; + return 0; } if (ev->unused.used > 0) { @@ -89,10 +66,11 @@ static int fdevent_poll_event_set(fdevents *ev, int fde_ndx, int fd, int events) k = ev->used++; } + fdn->fde_ndx = k; ev->pollfds[k].fd = fd; ev->pollfds[k].events = events; - return k; + return 0; } static int fdevent_poll_next_ndx(const fdevents *ev, int ndx) { @@ -106,8 +84,8 @@ static int fdevent_poll_poll(fdevents *ev, int timeout_ms) { const int n = poll(ev->pollfds, ev->used, timeout_ms); server * const srv = ev->srv; for (int ndx=-1,i=0; ipollfds[ndx].revents; fdnode *fdn = ev->fdarray[ev->pollfds[ndx].fd]; + int revents = ev->pollfds[ndx].revents; if (0 == ((uintptr_t)fdn & 0x3)) { (*fdn->handler)(srv, fdn->ctx, revents); } @@ -115,39 +93,24 @@ static int fdevent_poll_poll(fdevents *ev, int timeout_ms) { return n; } +__attribute_cold__ int fdevent_poll_init(fdevents *ev) { - ev->type = FDEVENT_HANDLER_POLL; force_assert(POLLIN == FDEVENT_IN); force_assert(POLLPRI == FDEVENT_PRI); force_assert(POLLOUT == FDEVENT_OUT); force_assert(POLLERR == FDEVENT_ERR); force_assert(POLLHUP == FDEVENT_HUP); force_assert(POLLNVAL == FDEVENT_NVAL); - #if 0 != POLLRDHUP + #ifdef POLLRDHUP force_assert(POLLRDHUP == FDEVENT_RDHUP); #endif -#define SET(x) \ - ev->x = fdevent_poll_##x; - - SET(free); - SET(poll); - - SET(event_del); - SET(event_set); + ev->type = FDEVENT_HANDLER_POLL; + ev->event_set = fdevent_poll_event_set; + ev->event_del = fdevent_poll_event_del; + ev->poll = fdevent_poll_poll; + ev->free = fdevent_poll_free; return 0; } - - - -#else -int fdevent_poll_init(fdevents *ev) { - UNUSED(ev); - - log_error_write(ev->srv, __FILE__, __LINE__, - "s", "poll is not supported, try to set server.event-handler = \"select\""); - - return -1; -} #endif diff --git a/src/fdevent_select.c b/src/fdevent_select.c index fe58ff8e..0848d679 100644 --- a/src/fdevent_select.c +++ b/src/fdevent_select.c @@ -3,39 +3,34 @@ #include "fdevent_impl.h" #include "fdevent.h" #include "buffer.h" -#include "log.h" #include -#include #include #include #include -#include #ifdef FDEVENT_USE_SELECT +__attribute_cold__ static int fdevent_select_reset(fdevents *ev) { FD_ZERO(&(ev->select_set_read)); FD_ZERO(&(ev->select_set_write)); FD_ZERO(&(ev->select_set_error)); ev->select_max_fd = -1; - return 0; } -static int fdevent_select_event_del(fdevents *ev, int fde_ndx, int fd) { - if (fde_ndx < 0) return -1; - +static int fdevent_select_event_del(fdevents *ev, fdnode *fdn) { + int fd = fdn->fd; FD_CLR(fd, &(ev->select_set_read)); FD_CLR(fd, &(ev->select_set_write)); FD_CLR(fd, &(ev->select_set_error)); - - return -1; + return 0; } -static int fdevent_select_event_set(fdevents *ev, int fde_ndx, int fd, int events) { - UNUSED(fde_ndx); +static int fdevent_select_event_set(fdevents *ev, fdnode *fdn, int events) { + int fd = fdn->fde_ndx = fdn->fd; /* we should be protected by max-fds, but you never know */ force_assert(fd < ((int)FD_SETSIZE)); @@ -54,31 +49,20 @@ static int fdevent_select_event_set(fdevents *ev, int fde_ndx, int fd, int event if (fd > ev->select_max_fd) ev->select_max_fd = fd; - return fd; + return 0; } static int fdevent_select_event_get_revent(const fdevents *ev, size_t ndx) { int revents = 0; - - if (FD_ISSET(ndx, &(ev->select_read))) { - revents |= FDEVENT_IN; - } - if (FD_ISSET(ndx, &(ev->select_write))) { - revents |= FDEVENT_OUT; - } - if (FD_ISSET(ndx, &(ev->select_error))) { - revents |= FDEVENT_ERR; - } - + if (FD_ISSET(ndx, &ev->select_read)) revents |= FDEVENT_IN; + if (FD_ISSET(ndx, &ev->select_write)) revents |= FDEVENT_OUT; + if (FD_ISSET(ndx, &ev->select_error)) revents |= FDEVENT_ERR; return revents; } static int fdevent_select_event_next_fdndx(const fdevents *ev, int ndx) { - int i; - - i = (ndx < 0) ? 0 : ndx + 1; - - for (; i < ev->select_max_fd + 1; i++) { + const int max_fd = ev->select_max_fd + 1; + for (int i = (ndx < 0) ? 0 : ndx + 1; i < max_fd; ++i) { if (FD_ISSET(i, &(ev->select_read))) return i; if (FD_ISSET(i, &(ev->select_write))) return i; if (FD_ISSET(i, &(ev->select_error))) return i; @@ -112,24 +96,14 @@ static int fdevent_select_poll(fdevents *ev, int timeout_ms) { return n; } +__attribute_cold__ int fdevent_select_init(fdevents *ev) { - ev->type = FDEVENT_HANDLER_SELECT; -#define SET(x) \ - ev->x = fdevent_select_##x; - - SET(reset); - SET(poll); - - SET(event_del); - SET(event_set); - + ev->type = FDEVENT_HANDLER_SELECT; + ev->event_set = fdevent_select_event_set; + ev->event_del = fdevent_select_event_del; + ev->poll = fdevent_select_poll; + ev->reset = fdevent_select_reset; return 0; } -#else -int fdevent_select_init(fdevents *ev) { - UNUSED(ev); - - return -1; -} #endif diff --git a/src/fdevent_solaris_devpoll.c b/src/fdevent_solaris_devpoll.c index dd54b47c..5b36af42 100644 --- a/src/fdevent_solaris_devpoll.c +++ b/src/fdevent_solaris_devpoll.c @@ -3,14 +3,10 @@ #include "fdevent_impl.h" #include "fdevent.h" #include "buffer.h" -#include "log.h" - -#include #include #include #include -#include #include #ifdef FDEVENT_USE_SOLARIS_DEVPOLL @@ -18,6 +14,7 @@ # include # include +__attribute_cold__ static void fdevent_solaris_devpoll_free(fdevents *ev) { free(ev->devpollfds); close(ev->devpoll_fd); @@ -25,41 +22,20 @@ static void fdevent_solaris_devpoll_free(fdevents *ev) { /* return -1 is fine here */ -static int fdevent_solaris_devpoll_event_del(fdevents *ev, int fde_ndx, int fd) { +static int fdevent_solaris_devpoll_event_del(fdevents *ev, fdnode *fdn) { struct pollfd pfd; - - if (fde_ndx < 0) return -1; - - pfd.fd = fd; + pfd.fd = fdn->fd; pfd.events = POLLREMOVE; pfd.revents = 0; - - if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) { - log_error_write(ev->srv, __FILE__, __LINE__, "S(D, S)", - "(del) write failed: ", fd, strerror(errno)); - - return -1; - } - - return -1; + return (-1 != write(ev->devpoll_fd, &pfd, sizeof(pfd))) ? 0 : -1; } -static int fdevent_solaris_devpoll_event_set(fdevents *ev, int fde_ndx, int fd, int events) { +static int fdevent_solaris_devpoll_event_set(fdevents *ev, fdnode *fdn, int events) { struct pollfd pfd; - int add = (-1 == fde_ndx); - - pfd.fd = fd; + pfd.fd = fdn->fde_ndx = fdn->fd; pfd.events = events; pfd.revents = 0; - - if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) { - log_error_write(ev->srv, __FILE__, __LINE__, "S(D, S)", - "(set) write failed: ", fd, strerror(errno)); - - return -1; - } - - return fd; + return (-1 != write(ev->devpoll_fd, &pfd, sizeof(pfd))) ? 0 : -1; } static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) { @@ -74,8 +50,8 @@ static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) { n = ioctl(ev->devpoll_fd, DP_POLL, &dopoll); for (int i = 0; i < n; ++i) { - int revents = ev->devpollfds[i].revents; fdnode * const fdn = ev->fdarray[ev->devpollfds[i].fd]; + int revents = ev->devpollfds[i].revents; if (0 == ((uintptr_t)fdn & 0x3)) { (*fdn->handler)(srv, fdn->ctx, revents); } @@ -83,21 +59,17 @@ static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) { return n; } +__attribute_cold__ int fdevent_solaris_devpoll_reset(fdevents *ev) { /* a forked process does only inherit the filedescriptor, * but every operation on the device will lead to a EACCES */ - if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) { - log_error_write(ev->srv, __FILE__, __LINE__, "SSS", - "opening /dev/poll failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\""); - - return -1; - } - + if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) return -1; fdevent_setfd_cloexec(ev->devpoll_fd); return 0; } + +__attribute_cold__ int fdevent_solaris_devpoll_init(fdevents *ev) { - ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL; force_assert(POLLIN == FDEVENT_IN); force_assert(POLLPRI == FDEVENT_PRI); force_assert(POLLOUT == FDEVENT_OUT); @@ -105,41 +77,17 @@ int fdevent_solaris_devpoll_init(fdevents *ev) { force_assert(POLLHUP == FDEVENT_HUP); force_assert(POLLNVAL == FDEVENT_NVAL); force_assert(POLLRDHUP == FDEVENT_RDHUP); -#define SET(x) \ - ev->x = fdevent_solaris_devpoll_##x; - - SET(free); - SET(poll); - SET(reset); - - SET(event_del); - SET(event_set); + ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL; + ev->event_set = fdevent_solaris_devpoll_event_set; + ev->event_del = fdevent_solaris_devpoll_event_del; + ev->poll = fdevent_solaris_devpoll_poll; + ev->reset = fdevent_solaris_devpoll_reset; + ev->free = fdevent_solaris_devpoll_free; + ev->devpoll_fd = -1; ev->devpollfds = malloc(sizeof(*ev->devpollfds) * ev->maxfds); force_assert(NULL != ev->devpollfds); - - if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) { - log_error_write(ev->srv, __FILE__, __LINE__, "SSS", - "opening /dev/poll failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\""); - - return -1; - } - - /* we just wanted to check if it works */ - close(ev->devpoll_fd); - - ev->devpoll_fd = -1; - return 0; } -#else -int fdevent_solaris_devpoll_init(fdevents *ev) { - UNUSED(ev); - - log_error_write(ev->srv, __FILE__, __LINE__, "S", - "solaris-devpoll not supported, try to set server.event-handler = \"poll\" or \"select\""); - - return -1; -} #endif diff --git a/src/fdevent_solaris_port.c b/src/fdevent_solaris_port.c index 37782936..c210a5a1 100644 --- a/src/fdevent_solaris_port.c +++ b/src/fdevent_solaris_port.c @@ -5,8 +5,6 @@ #include "buffer.h" #include "log.h" -#include - #include #include #include @@ -16,48 +14,18 @@ #ifdef FDEVENT_USE_SOLARIS_PORT #include -static const int SOLARIS_PORT_POLL_READ = POLLIN; -static const int SOLARIS_PORT_POLL_WRITE = POLLOUT; -static const int SOLARIS_PORT_POLL_READ_WRITE = POLLIN & POLLOUT; - -static int fdevent_solaris_port_event_del(fdevents *ev, int fde_ndx, int fd) { - if (fde_ndx < 0) return -1; - - if (0 != port_dissociate(ev->port_fd, PORT_SOURCE_FD, fd)) { - log_error_write(ev->srv, __FILE__, __LINE__, "SSS", - "port_dissociate failed: ", strerror(errno), ", dying"); - - SEGFAULT(); - return 0; - } - - return -1; +static int fdevent_solaris_port_event_del(fdevents *ev, fdnode *fdn) { + return port_dissociate(ev->port_fd, PORT_SOURCE_FD, fdn->fd); } -static int fdevent_solaris_port_event_set(fdevents *ev, int fde_ndx, int fd, int events) { - const int* user_data = NULL; - - if ((events & FDEVENT_IN) && (events & FDEVENT_OUT)) { - user_data = &SOLARIS_PORT_POLL_READ_WRITE; - } else if (events & FDEVENT_IN) { - user_data = &SOLARIS_PORT_POLL_READ; - } else if (events & FDEVENT_OUT) { - user_data = &SOLARIS_PORT_POLL_WRITE; - } - - if (0 != port_associate(ev->port_fd, PORT_SOURCE_FD, fd, *user_data, (void*) user_data)) { - log_error_write(ev->srv, __FILE__, __LINE__, "SSS", - "port_associate failed: ", strerror(errno), ", dying"); - - SEGFAULT(); - - return 0; - } - - return fd; +static int fdevent_solaris_port_event_set(fdevents *ev, fdnode *fdn, int events) { + int fd = fdn->fdn_ndx = fdn->fd; + intptr_t ud = events & (POLLIN|POLLOUT); + return port_associate(ev->port_fd,PORT_SOURCE_FD,fd,(int)ud,(void*)ud); } +__attribute_cold__ static void fdevent_solaris_port_free(fdevents *ev) { close(ev->port_fd); free(ev->port_events); @@ -65,10 +33,9 @@ static void fdevent_solaris_port_free(fdevents *ev) { /* if there is any error it will return the return values of port_getn, otherwise it will return number of events **/ static int fdevent_solaris_port_poll(fdevents *ev, int timeout_ms) { - int i = 0; + const int pfd = ev->port_fd; int ret; unsigned int available_events, wait_for_events = 0; - const int *user_data; struct timespec timeout; @@ -76,7 +43,7 @@ static int fdevent_solaris_port_poll(fdevents *ev, int timeout_ms) { timeout.tv_nsec = (timeout_ms % 1000L) * 1000000L; /* get the number of file descriptors with events */ - if ((ret = port_getn(ev->port_fd, ev->port_events, 0, &wait_for_events, &timeout)) < 0) return ret; + if ((ret = port_getn(pfd, ev->port_events, 0, &wait_for_events, &timeout)) < 0) return ret; /* wait for at least one event */ if (0 == wait_for_events) wait_for_events = 1; @@ -84,38 +51,33 @@ static int fdevent_solaris_port_poll(fdevents *ev, int timeout_ms) { available_events = wait_for_events; /* get the events of the file descriptors */ - if ((ret = port_getn(ev->port_fd, ev->port_events, ev->maxfds, &available_events, &timeout)) < 0) { + if ((ret = port_getn(pfd, ev->port_events, ev->maxfds, &available_events, &timeout)) < 0) { /* if errno == ETIME and available_event == wait_for_events we didn't get any events */ /* for other errors we didn't get any events either */ if (!(errno == ETIME && wait_for_events != available_events)) return ret; } - for (i = 0; i < (int)available_events; ++i) { - user_data = (const int *) ev->port_events[i].portev_user; - - if ((ret = port_associate(ev->port_fd, PORT_SOURCE_FD, ev->port_events[i].portev_object, - *user_data, (void*) user_data)) < 0) { - log_error_write(ev->srv, __FILE__, __LINE__, "SSS", - "port_associate failed: ", strerror(errno), ", dying"); - - SEGFAULT(); - - return 0; - } - } - - for (i = 0; i < available_events; ++i) { + for (int i = 0; i < (int)available_events; ++i) { + int fd = (int)ev->port_events[i].portev_object; + fdnode * const fdn = ev->fdarray[fd]; + const intptr_t ud = (intptr_t)ev->port_events[i].portev_user; int revents = ev->port_events[i].portev_events; - fdnode * const fdn = ev->fdarray[ev->port_events[i].portev_object]; if (0 == ((uintptr_t)fdn & 0x3)) { + if (port_associate(pfd,PORT_SOURCE_FD,fd,(int)ud,(void*)ud) < 0) { + log_error_write(ev->srv, __FILE__, __LINE__, "SS", + "port_associate failed: ", strerror(errno)); + } (*fdn->handler)(ev->srv, fdn->ctx, revents); } + else { + fdn->fde_ndx = -1; + } } return available_events; } +__attribute_cold__ int fdevent_solaris_port_init(fdevents *ev) { - ev->type = FDEVENT_HANDLER_SOLARIS_PORT; force_assert(POLLIN == FDEVENT_IN); force_assert(POLLPRI == FDEVENT_PRI); force_assert(POLLOUT == FDEVENT_OUT); @@ -123,35 +85,18 @@ int fdevent_solaris_port_init(fdevents *ev) { force_assert(POLLHUP == FDEVENT_HUP); force_assert(POLLNVAL == FDEVENT_NVAL); force_assert(POLLRDHUP == FDEVENT_RDHUP); -#define SET(x) \ - ev->x = fdevent_solaris_port_##x; - - SET(free); - SET(poll); - - SET(event_del); - SET(event_set); - - if ((ev->port_fd = port_create()) < 0) { - log_error_write(ev->srv, __FILE__, __LINE__, "SSS", - "port_create() failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\""); - - return -1; - } + ev->type = FDEVENT_HANDLER_SOLARIS_PORT; + ev->event_set = fdevent_solaris_port_event_set; + ev->event_del = fdevent_solaris_port_event_del; + ev->poll = fdevent_solaris_port_poll; + ev->free = fdevent_solaris_port_free; ev->port_events = malloc(ev->maxfds * sizeof(*ev->port_events)); force_assert(NULL != ev->port_events); + if ((ev->port_fd = port_create()) < 0) return -1; + return 0; } -#else -int fdevent_solaris_port_init(fdevents *ev) { - UNUSED(ev); - - log_error_write(ev->srv, __FILE__, __LINE__, "S", - "solaris-eventports not supported, try to set server.event-handler = \"poll\" or \"select\""); - - return -1; -} #endif