static int add_fd(os_handler_t *handler, int fd, os_data_ready_t data_ready, void *cb_data, os_fd_data_freed_t freed, os_hnd_fd_id_t **id) { os_hnd_fd_id_t *fd_data; int rv; pt_os_hnd_data_t *info = handler->internal_data; selector_t *posix_sel = info->sel; fd_data = malloc(sizeof(*fd_data)); if (!fd_data) return ENOMEM; fd_data->fd = fd; fd_data->cb_data = cb_data; fd_data->data_ready = data_ready; fd_data->handler = handler; fd_data->freed = freed; sel_set_fd_write_handler(posix_sel, fd, SEL_FD_HANDLER_DISABLED); sel_set_fd_except_handler(posix_sel, fd, SEL_FD_HANDLER_DISABLED); rv = sel_set_fd_handlers(posix_sel, fd, fd_data, fd_handler, NULL, NULL, free_fd_data); if (rv) { free(fd_data); return rv; } sel_set_fd_read_handler(posix_sel, fd, SEL_FD_HANDLER_ENABLED); *id = fd_data; return 0; }
static int set_fd_enables(os_handler_t *handler, os_hnd_fd_id_t *id, int read, int write, int except) { iposix_info_t *info = handler->internal_data; selector_t *posix_sel = info->sel; if (read) read = SEL_FD_HANDLER_ENABLED; else read = SEL_FD_HANDLER_DISABLED; if (write) write = SEL_FD_HANDLER_ENABLED; else write = SEL_FD_HANDLER_DISABLED; if (except) except = SEL_FD_HANDLER_ENABLED; else except = SEL_FD_HANDLER_DISABLED; sel_set_fd_read_handler(posix_sel, id->fd, read); sel_set_fd_write_handler(posix_sel, id->fd, write); sel_set_fd_except_handler(posix_sel, id->fd, except); return 0; }
void sel_select_once(selector_t *sel) { fd_set tmp_read_set; fd_set tmp_write_set; fd_set tmp_except_set; int i; int err; sel_timer_t *timer; struct timeval timeout, *to_time; if (sel->timer_top) { struct timeval now; /* Check for timers to time out. */ gettimeofday(&now, NULL); timer = sel->timer_top; while (cmp_timeval(&now, &timer->timeout) >= 0) { remove_from_heap(&(sel->timer_top), &(sel->timer_last), timer); timer->in_heap = 0; timer->handler(sel, timer, timer->user_data); timer = sel->timer_top; gettimeofday(&now, NULL); if (!timer) goto no_timers; } /* Calculate how long to wait now. */ diff_timeval(&timeout, &sel->timer_top->timeout, &now); to_time = &timeout; } else { no_timers: to_time = NULL; } memcpy(&tmp_read_set, &sel->read_set, sizeof(tmp_read_set)); memcpy(&tmp_write_set, &sel->write_set, sizeof(tmp_write_set)); memcpy(&tmp_except_set, &sel->except_set, sizeof(tmp_except_set)); err = select(sel->maxfd+1, &tmp_read_set, &tmp_write_set, &tmp_except_set, to_time); if (err == 0) { /* A timeout occurred. */ } else if (err < 0) { /* An error occurred. */ if (errno == EINTR) { /* EINTR is ok, just restart the operation. */ timeout.tv_sec = 1; timeout.tv_usec = 0; } else { /* An error is bad, we need to abort. */ syslog(LOG_ERR, "select_loop() - select: %m"); exit(1); } } else { /* We got some I/O. */ for (i=0; i<=sel->maxfd; i++) { if (FD_ISSET(i, &tmp_read_set)) { if (sel->fds[i].handle_read == NULL) { /* Somehow we don't have a handler for this. Just shut it down. */ sel_set_fd_read_handler(sel, i, SEL_FD_HANDLER_DISABLED); } else { sel->fds[i].handle_read(i, sel->fds[i].data); } } if (FD_ISSET(i, &tmp_write_set)) { if (sel->fds[i].handle_write == NULL) { /* Somehow we don't have a handler for this. Just shut it down. */ sel_set_fd_write_handler(sel, i, SEL_FD_HANDLER_DISABLED); } else { sel->fds[i].handle_write(i, sel->fds[i].data); } } if (FD_ISSET(i, &tmp_except_set)) { if (sel->fds[i].handle_except == NULL) { /* Somehow we don't have a handler for this. Just shut it down. */ sel_set_fd_except_handler(sel, i, SEL_FD_HANDLER_DISABLED); } else { sel->fds[i].handle_except(i, sel->fds[i].data); } } } } if (got_sighup) { got_sighup = 0; if (user_sighup_handler != NULL) { user_sighup_handler(); } } if (got_sigint) { got_sigint = 0; if (user_sigint_handler != NULL) { user_sigint_handler(); } } }
/* * return == 0 when timeout * > 0 when successful * < 0 when error */ static int process_fds(selector_t *sel, sel_send_sig_cb send_sig, long thread_id, void *cb_data, volatile struct timeval *timeout) { fd_set tmp_read_set; fd_set tmp_write_set; fd_set tmp_except_set; int i; int err; int num_fds; if (sel->have_fd_lock) sel->os_hnd->lock(sel->os_hnd, sel->fd_lock); memcpy(&tmp_read_set, (void *) &sel->read_set, sizeof(tmp_read_set)); memcpy(&tmp_write_set, (void *) &sel->write_set, sizeof(tmp_write_set)); memcpy(&tmp_except_set, (void *) &sel->except_set, sizeof(tmp_except_set)); num_fds = sel->maxfd+1; if (sel->add_read) { int timeout_invalid; struct timeval ttimeout; timeout_invalid = 1; sel->add_read(sel, &num_fds, &tmp_read_set, &ttimeout, &timeout_invalid, sel->read_cb_data); if (!timeout_invalid && (cmp_timeval(&ttimeout, (struct timeval *)timeout) <= 0)) { *timeout= ttimeout; } } if (sel->have_fd_lock) sel->os_hnd->unlock(sel->os_hnd, sel->fd_lock); err = select(num_fds, &tmp_read_set, &tmp_write_set, &tmp_except_set, (struct timeval *) timeout); if (err <= 0) { if ((err == 0) && (sel->check_timeout)) sel->check_timeout(sel, sel->read_cb_data); goto out; } if (sel->check_read) sel->check_read(sel, &tmp_read_set, sel->read_cb_data); /* We got some I/O. */ for (i=0; i<=sel->maxfd; i++) { if (FD_ISSET(i, &tmp_read_set)) { sel_fd_handler_t handle_read; void *data; fd_state_t *state; if (sel->have_fd_lock) sel->os_hnd->lock(sel->os_hnd, sel->fd_lock); if (sel->fds[i].handle_read == NULL) { /* Somehow we don't have a handler for this. Just shut it down. */ sel_set_fd_read_handler(sel, i, SEL_FD_HANDLER_DISABLED); } else { handle_read = sel->fds[i].handle_read; data = sel->fds[i].data; state = sel->fds[i].state; state->use_count++; if (sel->have_fd_lock) sel->os_hnd->unlock(sel->os_hnd, sel->fd_lock); handle_read(i, data); if (sel->have_fd_lock) sel->os_hnd->lock(sel->os_hnd, sel->fd_lock); state->use_count--; if (state->deleted && state->use_count == 0) { if (state->done) state->done(i, data); free(state); } } if (sel->have_fd_lock) sel->os_hnd->unlock(sel->os_hnd, sel->fd_lock); } if (FD_ISSET(i, &tmp_write_set)) { sel_fd_handler_t handle_write; void *data; fd_state_t *state; if (sel->have_fd_lock) sel->os_hnd->lock(sel->os_hnd, sel->fd_lock); if (sel->fds[i].handle_write == NULL) { /* Somehow we don't have a handler for this. Just shut it down. */ sel_set_fd_write_handler(sel, i, SEL_FD_HANDLER_DISABLED); } else { handle_write = sel->fds[i].handle_write; data = sel->fds[i].data; state = sel->fds[i].state; state->use_count++; if (sel->have_fd_lock) sel->os_hnd->unlock(sel->os_hnd, sel->fd_lock); handle_write(i, data); if (sel->have_fd_lock) sel->os_hnd->lock(sel->os_hnd, sel->fd_lock); state->use_count--; if (state->deleted && state->use_count == 0) { if (state->done) state->done(i, data); free(state); } } if (sel->have_fd_lock) sel->os_hnd->unlock(sel->os_hnd, sel->fd_lock); } if (FD_ISSET(i, &tmp_except_set)) { sel_fd_handler_t handle_except; void *data; fd_state_t *state; if (sel->have_fd_lock) sel->os_hnd->lock(sel->os_hnd, sel->fd_lock); if (sel->fds[i].handle_except == NULL) { /* Somehow we don't have a handler for this. Just shut it down. */ sel_set_fd_except_handler(sel, i, SEL_FD_HANDLER_DISABLED); } else { handle_except = sel->fds[i].handle_except; data = sel->fds[i].data; state = sel->fds[i].state; state->use_count++; if (sel->have_fd_lock) sel->os_hnd->unlock(sel->os_hnd, sel->fd_lock); handle_except(i, data); if (sel->have_fd_lock) sel->os_hnd->lock(sel->os_hnd, sel->fd_lock); state->use_count--; if (state->deleted && state->use_count == 0) { if (state->done) state->done(i, data); free(state); } } if (sel->have_fd_lock) sel->os_hnd->unlock(sel->os_hnd, sel->fd_lock); } } out: return err; }