static void server_cleanup( struct server* srv_ptr ) { assert(srv_ptr); /* * Fallthrough is intended. */ switch (srv_ptr->sv_rollback) { case 5 : for (long i = 0; i < srv_ptr->sv_worker_count; ++i) { worker_thread_destroy(srv_ptr->sv_workers[i]); } srv_ptr->sv_allocator->al_mem_release(srv_ptr->sv_allocator, srv_ptr->sv_workers); case 4 : HANDLE_EINTR_ON_SYSCALL(close(srv_ptr->sv_threadrdy_eventfds)); case 3 : HANDLE_EINTR_ON_SYSCALL(close(srv_ptr->sv_sigfds)); case 2 : HANDLE_EINTR_ON_SYSCALL(close(srv_ptr->sv_epollfd)); case 1 : HANDLE_EINTR_ON_SYSCALL(close(srv_ptr->sv_acceptfd)); default : break; } }
void prm_destroy() { DEBUG("PRM exiting\n"); worker_thread_stop(&prm_thread); worker_thread_destroy(&prm_thread); assert(queue_size(prm_queue) == 0); pthread_mutex_destroy(&prm_mutex); pthread_mutex_destroy(&prm_queue_mutex); pthread_cond_destroy(&prm_queue_condvar); pthread_cond_destroy(&prm_condvar); queue_destroy(prm_queue); DEBUG("PRM exited\n"); }
static int server_init( struct server* p_srv ) { assert(p_srv); memset(p_srv, 0, sizeof(*p_srv)); p_srv->sv_allocator = allocator_handle; p_srv->sv_quitflag = 0; p_srv->sv_acceptfd = create_server_socket(); if (-1 == p_srv->sv_acceptfd) { return -1; } /* * Level 1 - accept socket created. */ ++p_srv->sv_rollback; p_srv->sv_epollfd = epoll_create(kMaxEpollCompletionEntries); if (-1 == p_srv->sv_epollfd) { return -1; } /* * Level 2 - epoll descriptor allocated. */ ++p_srv->sv_rollback; /* * Block SIGINT and create a signal descriptor to receive it via epoll. */ sigset_t sig_mask; sigemptyset(&sig_mask); if (-1 == sigaddset(&sig_mask, SIGINT)) { return -1; } if (-1 == sigprocmask(SIG_BLOCK, &sig_mask, NULL)) { return -1; } p_srv->sv_sigfds = signalfd(-1, &sig_mask, SFD_NONBLOCK); if (-1 == p_srv->sv_sigfds) { return -1; } /* * Level 3 - signal descriptor for SIGINT allocated. */ ++p_srv->sv_rollback; /* * Add termination signal and accept socket to epoll interface. */ if (-1 == add_fd_to_epoll(p_srv->sv_epollfd, p_srv->sv_sigfds, EPOLLIN | EPOLLET, kDataTypeFD, p_srv->sv_sigfds)) { return -1; } if (-1 == add_fd_to_epoll(p_srv->sv_epollfd, p_srv->sv_acceptfd, EPOLLIN | EPOLLET | EPOLLRDHUP, kDataTypeFD, p_srv->sv_acceptfd)) { return -1; } p_srv->sv_threadrdy_eventfds = eventfd(0, 0); if (p_srv->sv_threadrdy_eventfds == -1) { D_FUNCFAIL_ERRNO(eventfd); return -1; } /* * Level 4 - thread notification event created. */ ++p_srv->sv_rollback; /* * Get number of available processors. The number of spawned threads is * nr_processors * thread_to_proc_ratio. */ long nr_procs = sysconf(_SC_NPROCESSORS_ONLN); if (nr_procs == -1) { D_FUNCFAIL_ERRNO(sysconf); return -1; } D_FMTSTRING("Online processors %d, will spawn %d threads.", nr_procs, nr_procs); p_srv->sv_workers = p_srv->sv_allocator->al_mem_alloc( p_srv->sv_allocator, (sizeof(struct worker_thread*) * nr_procs)); if (!p_srv->sv_workers) { D_FMTSTRING("Out of memory!"); return -1; } /* * Level 5 - memory for worker thread data allocated. */ ++p_srv->sv_rollback; memset(p_srv->sv_workers, 0, sizeof(struct worker_thread*) * nr_procs); /* * Initialize data and start worker threads. */ for (long l = 0; l < nr_procs; ++l) { char thread_msgqueue[NAME_MAX]; snprintf(thread_msgqueue, sizeof(thread_msgqueue) - 1, "/__msgqueue_thread_%d__", (int) l); struct worker_thread* current = worker_thread_create(thread_msgqueue, p_srv->sv_allocator); if (current) { if (worker_thread_start(p_srv, current, NULL) == 0) { /* * Thread successfully initialized, add it to list. */ p_srv->sv_workers[p_srv->sv_worker_count++] = current; } else { /* * Cleanup thread data since pthread_create() failed. */ worker_thread_destroy(current); } } } if (!p_srv->sv_worker_count) { D_FMTSTRING("Fatal : failed to initialize at least one worker thread!"); return -1; } D_FMTSTRING("Started a total of %d worker threads", p_srv->sv_worker_count); /* * Server is up and running. */ return 0; }