/** * @short Advises the listener to stop. * * The listener is advised to stop listening. After this call no listening is still open, and listen could be * called again, or the onion server freed. * * If there is any pending connection, it can finish if onion not freed before. */ void onion_listen_stop(onion* server){ /// Start listening onion_listen_point **lp=server->listen_points; while (*lp){ onion_listen_point_listen_stop(*lp); lp++; } if (server->poller){ ONION_DEBUG("Stop listening"); onion_poller_stop(server->poller); } #ifdef HAVE_PTHREADS if (server->flags&O_DETACHED) pthread_join(server->listen_thread, NULL); #endif }
/** * @short Removes a file descriptor, and all related callbacks from the listening queue * @memberof onion_poller_t * @ingroup poller */ int onion_poller_remove(onion_poller *poller, int fd){ if (epoll_ctl(poller->fd, EPOLL_CTL_DEL, fd, NULL) < 0){ if (errno!=ENOENT && errno!=EBADF){ ONION_ERROR("Error remove descriptor to listen to. %s (%d)", strerror(errno), errno); } } pthread_mutex_lock(&poller->mutex); ONION_DEBUG0("Trying to remove fd %d (%d)", fd, poller->n); onion_poller_slot *el=poller->head; if (el && el->fd==fd){ ONION_DEBUG0("Removed from head %p", el); poller->head=el->next; pthread_mutex_unlock(&poller->mutex); onion_poller_slot_free(el); return 0; } while (el->next){ if (el->next->fd==fd){ ONION_DEBUG0("Removed from tail %p",el); onion_poller_slot *t=el->next; el->next=t->next; if (poller->head->next==NULL){ // This means only eventfd is here. ONION_DEBUG0("Removed last, stopping poll"); onion_poller_stop(poller); } pthread_mutex_unlock(&poller->mutex); onion_poller_slot_free(t); return 0; } el=el->next; } pthread_mutex_unlock(&poller->mutex); ONION_WARNING("Trying to remove unknown fd from poller %d", fd); return 0; }
static int onion_poller_stop_helper(void *p){ onion_poller_stop(p); return 1; }