/*- * Copyright (c) 2001, 2002, 2004 Lev Walkin . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: servers.c,v 1.10 2006/04/07 18:58:02 vlm Exp $ */ #include "ipcad.h" #include "servers.h" #include "opt.h" server *servers_head = NULL; int add_server(void *(*func)(void *), char *name, struct in_addr *ip, int hport) { server *srv; if(!func || !name) return -1; srv = (server *)calloc(1, sizeof(server)); if(!srv) return -1; srv->name = strdup(name); if(!srv->name) { free(srv); return -1; } srv->server_func = func; srv->addr.sin_family = AF_INET; if(ip) srv->addr.sin_addr = *ip; srv->addr.sin_port = htons(hport); srv->sockfd = -1; srv->next = servers_head; servers_head = srv; return 0; } int start_servers() { sigset_t old_set; server *srv; int rc; if(!servers_head) { if(daemon_mode) printf("No servers defined. How will you gather data? ;)\n"); return 0; } /* * Do not allow other threads receive signals for the main thread. * The signal mask is inherited from the creating thread. */ block_certain_signals(&old_set); /* Iterate through defined servers */ for(srv = servers_head; srv; srv=srv->next) { if(srv->started_ok) continue; rc = pthread_create(&srv->thid, NULL, srv->server_func, (void *)srv); if(rc == 0) { /* Wait for thread to terminate or report success */ while( (pthread_kill(srv->thid, 0) == 0) && (srv->started_ok == 0) ) { #ifdef HAVE_SCHED_YIELD sched_yield(); #else sleep(1); #endif } if(!srv->started_ok) rc = -1; } /* Failed to create particular server */ if(rc == -1) { srv->thid = 0; /* Terminate previously started servers */ end_servers(); sigprocmask(SIG_SETMASK, &old_set, NULL); return -1; } printf("%s thread %lu started.\n", srv->name, (long)srv->thid); } sigprocmask(SIG_SETMASK, &old_set, NULL); return 0; } void end_servers_r(server *srv) { if(!srv) return; if(srv->next) end_servers_r(srv->next); /* If alive */ if(srv->thid && srv->started_ok) { /* Kick it */ pthread_kill(srv->thid, SIGALRM); printf("Waiting for %s thread to terminate... ", srv->name); fflush(stdout); pthread_join(srv->thid, NULL); printf("DONE.\n"); } /* if(thid) */ free(srv); } void end_servers() { sig_atomic_t tmps; /* Remember value */ tmps = signoff_now; /* Enable global signoff flag */ signoff_now = 1; /* Terminate working servers */ end_servers_r(servers_head); servers_head = NULL; /* Restore previous value */ signoff_now = tmps; }