Changeset 644

Show
Ignore:
Timestamp:
05/29/05 22:35:58 (3 years ago)
Author:
minaguib
Message:

* New wdctl command "restart" which will get wifidog to restart itself while preserving the existing clientlist. Perfect for 0-downtime upgrading!
* safe.c: New safe_fork that croaks if the fork fails, also takes care of closing some global file descriptors for the child
* debug.c: Now also logs the PID as part of every entry
* gateway.c: Handler for SIGCHLD now waitpid()s with WNOHANG flag to prevent deadlock when the handler is called and another wait() or waitpid() is used
* util.c: execute() now uses waitpid() instead of wait() to reap only the child it fork/executed
* Extra debugging entries throughout code

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/wdctlrestart/wifidog/ChangeLog

    r639 r644  
    11# $Header$ 
     2 
     32005-05-26 Mina Naguib <mina@ilesansfil.org> 
     4        * New wdctl command "restart" which will get wifidog to restart itself 
     5        while preserving the existing clientlist.  Perfect for 0-downtime 
     6        upgrading! 
     7        * safe.c: New safe_fork that croaks if the fork fails, also takes care of 
     8        closing some global file descriptors for the child 
     9        * debug.c: Now also logs the PID as part of every entry 
     10        * gateway.c: Handler for SIGCHLD now waitpid()s with WNOHANG flag to prevent deadlock 
     11        when the handler is called and another wait() or waitpid() is used 
     12        * util.c: execute() now uses waitpid() instead of wait() to reap only the child 
     13        it fork/executed 
     14        * Extra debugging entries throughout code 
    215 
    3162005-05-24 Mina Naguib <mina@ilesansfil.org> 
  • branches/wdctlrestart/wifidog/src/client_list.c

    r467 r644  
    5151 * Holds a pointer to the first element of the list  
    5252 */  
    53 static t_client         *firstclient = NULL; 
     53t_client         *firstclient = NULL; 
    5454 
    5555/** Get the first element of the list of connected clients 
     
    9696    curclient->mac = safe_strdup(mac); 
    9797    curclient->token = safe_strdup(token); 
    98     curclient->counters.incoming = curclient->counters.outgoing = 0; 
     98    curclient->counters.incoming = curclient->counters.incoming_history = curclient->counters.outgoing = curclient->counters.outgoing_history = 0; 
    9999    curclient->counters.last_updated = time(NULL); 
    100100 
  • branches/wdctlrestart/wifidog/src/client_list.h

    r471 r644  
    3131 */ 
    3232typedef struct _t_counters { 
    33     unsigned long long  incoming;       /**< @brief Incoming data */ 
    34     unsigned long long  outgoing;       /**< @brief Outgoing data */ 
     33    unsigned long long  incoming;       /**< @brief Incoming data total*/ 
     34    unsigned long long  outgoing;       /**< @brief Outgoing data total*/ 
     35    unsigned long long  incoming_history;       /**< @brief Incoming data before wifidog restarted*/ 
     36    unsigned long long  outgoing_history;       /**< @brief Outgoing data before wifidog restarted*/ 
    3537    time_t      last_updated;   /**< @brief Last update of the counters */ 
    3638} t_counters; 
  • branches/wdctlrestart/wifidog/src/commandline.c

    r467 r644  
    2929#include <unistd.h> 
    3030#include <string.h> 
     31#include <syslog.h> 
    3132 
     33#include "debug.h" 
    3234#include "safe.h" 
    3335#include "conf.h" 
     
    3537#include "../config.h" 
    3638 
     39/* 
     40 * Holds an argv that could be passed to exec*() if we restart ourselves 
     41 */ 
     42char ** restartargv = NULL; 
     43 
    3744static void usage(void); 
     45 
     46/* 
     47 * A flag to denote whether we were restarted via a parent wifidog, or started normally 
     48 * 0 means normally, otherwise it will be populated by the PID of the parent 
     49 */ 
     50pid_t restarted = 0; 
    3851 
    3952/** @internal 
     
    5467    printf("  -h            Print usage\n"); 
    5568    printf("  -v            Print version information\n"); 
     69    printf("  -x pid        Used internally by WiFiDog when re-starting itself *DO NOT ISSUE THIS SWITCH MANUAlLY*\n"); 
     70    printf("  -i <path>     Internal socket path used when re-starting self\n"); 
    5671    printf("\n"); 
    5772} 
    5873 
    5974/** Uses getopt() to parse the command line and set configuration values 
     75 * also populates restartargv 
    6076 */ 
    61 void 
    62 parse_commandline(int argc, char **argv) 
    63 
     77void parse_commandline(int argc, char **argv) { 
    6478    int c; 
     79         int skiponrestart; 
     80         int i; 
     81 
    6582    s_config *config = config_get_config(); 
    6683 
    67     while (-1 != (c = getopt(argc, argv, "c:hfd:sw:v"))) { 
    68         switch(c) { 
    69             case 'h': 
    70                 usage(); 
    71                 exit(1); 
    72                 break; 
     84        //MAGIC 3: Our own -x, the pid, and NULL : 
     85        restartargv = safe_malloc((argc + 3) * sizeof(char*)); 
     86        i=0; 
     87        restartargv[i++] = safe_strdup(argv[0]); 
    7388 
    74             case 'c': 
    75                 if (optarg) { 
    76                     strncpy(config->configfile, optarg, sizeof(config->configfile)); 
    77                 } 
    78                 break; 
     89    while (-1 != (c = getopt(argc, argv, "c:hfd:sw:vx:i:"))) { 
    7990 
    80             case 'w': 
    81                 if (optarg) { 
    82                     free(config->wdctl_sock); 
    83                     config->wdctl_sock = safe_strdup(optarg); 
     91                skiponrestart = 0; 
     92 
     93                switch(c) { 
     94 
     95                        case 'h': 
     96                                usage(); 
     97                                exit(1); 
     98                                break; 
     99 
     100                        case 'c': 
     101                                if (optarg) { 
     102                                        strncpy(config->configfile, optarg, sizeof(config->configfile)); 
     103                                } 
     104                                break; 
     105 
     106                        case 'w': 
     107                                if (optarg) { 
     108                                        free(config->wdctl_sock); 
     109                                        config->wdctl_sock = safe_strdup(optarg); 
     110                                } 
     111                                break; 
     112 
     113                        case 'f': 
     114                                skiponrestart = 1; 
     115                                config->daemon = 0; 
     116                                break; 
     117 
     118                        case 'd': 
     119                                if (optarg) { 
     120                                        config->debuglevel = atoi(optarg); 
     121                                } 
     122                                break; 
     123 
     124                        case 's': 
     125                                config->log_syslog = 1; 
     126                                break; 
     127 
     128                        case 'v': 
     129                                printf("This is WiFiDog version " VERSION "\n"); 
     130                                exit(1); 
     131                                break; 
     132 
     133                        case 'x': 
     134                                skiponrestart = 1; 
     135                                if (optarg) { 
     136                                        restarted = atoi(optarg); 
     137                                } 
     138                                else { 
     139                                        printf("The expected PID to the -x switch was not supplied!"); 
     140                                        exit(1); 
     141                                } 
     142                                break; 
     143 
     144                        case 'i': 
     145                                if (optarg) { 
     146                                        free(config->internal_sock); 
     147                                        config->internal_sock = safe_strdup(optarg); 
     148                                } 
     149                                break; 
     150 
     151                        default: 
     152                                usage(); 
     153                                exit(1); 
     154                                break; 
     155 
    84156                } 
    85                 break; 
    86157 
    87             case 'f': 
    88                 config->daemon = 0; 
    89                 break; 
     158                if (!skiponrestart) { 
     159                        /* Add it to restartargv */ 
     160                        safe_asprintf(&(restartargv[i++]), "-%c", c); 
     161                        if (optarg) { 
     162                                restartargv[i++] = safe_strdup(optarg); 
     163                        } 
     164                } 
    90165 
    91             case 'd': 
    92                 if (optarg) { 
    93                     config->debuglevel = atoi(optarg); 
    94                 } 
    95                 break; 
     166        } 
    96167 
    97             case 's': 
    98                 config->log_syslog = 1; 
    99                 break; 
     168        /* Finally, we should add  the -x, pid and NULL to restartargv 
     169         * HOWEVER we cannot do it here, since this is called before we fork to background 
     170         * so we'll leave this job to gateway.c after forking is completed 
     171         * so that the correct PID is assigned 
     172         * 
     173         * We add 3 nulls, and the first 2 will be overridden later 
     174         */ 
     175        restartargv[i++] = NULL; 
     176        restartargv[i++] = NULL; 
     177        restartargv[i++] = NULL; 
    100178 
    101                                 case 'v': 
    102                                          printf("This is WiFiDog version " VERSION "\n"); 
    103                                          exit(1); 
    104                                          break; 
    105  
    106             default: 
    107                 usage(); 
    108                 exit(1); 
    109                 break; 
    110         } 
    111     } 
    112179} 
    113180 
  • branches/wdctlrestart/wifidog/src/conf.c

    r491 r644  
    158158        config.log_syslog = DEFAULT_LOG_SYSLOG; 
    159159        config.wdctl_sock = safe_strdup(DEFAULT_WDCTL_SOCK); 
     160        config.internal_sock = safe_strdup(DEFAULT_INTERNAL_SOCK); 
    160161        config.rulesets = NULL; 
    161162} 
  • branches/wdctlrestart/wifidog/src/conf.h

    r290 r644  
    4242#define DEFAULT_SYSLOG_FACILITY LOG_DAEMON 
    4343#define DEFAULT_WDCTL_SOCK "/tmp/wdctl.sock" 
     44#define DEFAULT_INTERNAL_SOCK "/tmp/wifidog.sock" 
    4445#define DEFAULT_AUTHSERVPORT 80 
    4546#define DEFAULT_AUTHSERVSSLPORT 443 
     
    9293    char configfile[255];       /**< @brief name of the config file */ 
    9394    char *wdctl_sock;           /**< @brief wdctl path to socket */ 
     95    char *internal_sock;                /**< @brief internal path to socket */ 
    9496    int daemon;                 /**< @brief if daemon > 0, use daemon mode */ 
    9597    int debuglevel;             /**< @brief Debug information verbosity */ 
  • branches/wdctlrestart/wifidog/src/debug.c

    r243 r644  
    4949 
    5050        if (level <= LOG_WARNING) { 
    51             fprintf(stderr, "[%d][%.24s](%s:%d) ", level, ctime_r(&ts, buf), 
     51            fprintf(stderr, "[%d][%.24s][%u](%s:%d) ", level, ctime_r(&ts, buf), getpid(), 
    5252                            filename, line); 
    5353            vfprintf(stderr, format, vlist); 
    5454            fputc('\n', stderr); 
    5555        } else if (!config->daemon) { 
    56             fprintf(stdout, "[%d][%.24s](%s:%d) ", level, ctime_r(&ts, buf), 
     56            fprintf(stdout, "[%d][%.24s][%u](%s:%d) ", level, ctime_r(&ts, buf), getpid(), 
    5757                            filename, line); 
    5858            vfprintf(stdout, format, vlist); 
  • branches/wdctlrestart/wifidog/src/firewall.c

    r490 r644  
    7070extern pthread_mutex_t client_list_mutex; 
    7171 
     72/* from commandline.c */ 
     73extern pid_t restarted; 
     74 
    7275int icmp_fd = 0; 
    7376 
     
    144147{ 
    145148    int flags, oneopt = 1, zeroopt = 0; 
     149         int result = 0; 
     150         t_client * client = NULL; 
    146151 
    147152    debug(LOG_INFO, "Creating ICMP socket"); 
     
    156161 
    157162    debug(LOG_INFO, "Initializing Firewall"); 
    158     return iptables_fw_init(); 
     163    result = iptables_fw_init(); 
     164 
     165         if (restarted) { 
     166                 debug(LOG_INFO, "Restoring firewall rules for clients inherited from parent"); 
     167                 LOCK_CLIENT_LIST(); 
     168                 client = client_get_first_client(); 
     169                 while (client) { 
     170                         fw_allow(client->ip, client->mac, client->fw_connection_state); 
     171                         client = client->next; 
     172                 } 
     173                 UNLOCK_CLIENT_LIST(); 
     174         } 
     175 
     176         return result; 
    159177} 
    160178 
     
    269287                            fw_deny(p1->ip, p1->mac, p1->fw_connection_state); 
    270288                            p1->fw_connection_state = FW_MARK_KNOWN; 
    271                             p1->counters.incoming = p1->counters.outgoing = 0; 
     289                            p1->counters.incoming = p1->counters.outgoing = p1->counters.incoming_history = p1->counters.outgoing_history = 0; 
    272290                            fw_allow(p1->ip, p1->mac, p1->fw_connection_state); 
    273291                        } 
  • branches/wdctlrestart/wifidog/src/fw_iptables.c

    r634 r644  
    468468            LOCK_CLIENT_LIST(); 
    469469            if ((p1 = client_list_find_by_ip(ip))) { 
    470                 if (p1->counters.outgoing < counter) { 
    471                     p1->counters.outgoing = counter; 
     470                if ((p1->counters.outgoing - p1->counters.outgoing_history) < counter) { 
     471                    p1->counters.outgoing = p1->counters.outgoing_history + counter; 
    472472                    p1->counters.last_updated = time(NULL); 
    473473                    debug(LOG_DEBUG, "%s - Updated counter.outgoing to %llu bytes", ip, counter); 
     
    506506            LOCK_CLIENT_LIST(); 
    507507            if ((p1 = client_list_find_by_ip(ip))) { 
    508                 if (p1->counters.incoming < counter) { 
    509                     p1->counters.incoming = counter; 
     508                if ((p1->counters.incoming - p1->counters.incoming_history) < counter) { 
     509                    p1->counters.incoming = p1->counters.incoming_history + counter; 
    510510                    debug(LOG_DEBUG, "%s - Updated counter.incoming to %llu bytes", ip, counter); 
    511511                } 
  • branches/wdctlrestart/wifidog/src/gateway.c

    r495 r644  
    3535#include <time.h> 
    3636 
    37 /* for fork() */ 
    38 #include <sys/types.h> 
    39 #include <unistd.h> 
    40  
    4137/* for strerror() */ 
    4238#include <string.h> 
     
    4541#include <sys/wait.h> 
    4642 
     43/* for unix socket communication*/ 
     44#include <sys/socket.h> 
     45#include <sys/un.h> 
     46 
     47#include "common.h" 
    4748#include "httpd.h" 
    4849#include "safe.h" 
     
    6768static pthread_t tid_ping = 0;  
    6869 
     70/* The internal web server */ 
     71httpd * webserver = NULL; 
     72 
     73/* from commandline.c */ 
     74extern char ** restartargv; 
     75extern pid_t restarted; 
     76t_client *firstclient; 
     77 
     78/* from client_list.c */ 
     79extern pthread_mutex_t client_list_mutex; 
     80 
     81/* Appends -x, the current PID, and NULL to restartargv 
     82 * see parse_commandline in commandline.c for details 
     83 */ 
     84void append_x_restartargv(void) { 
     85        int i; 
     86 
     87        for (i=0; restartargv[i]; i++); 
     88 
     89        restartargv[i++] = safe_strdup("-x"); 
     90        safe_asprintf(&(restartargv[i++]), "%d", getpid()); 
     91} 
     92 
     93/* @internal 
     94 * @brief Connects to the parent via the internal socket 
     95 * Downloads from it the active client list 
     96 */ 
     97void get_clients_from_parent(void) { 
     98        int sock; 
     99        struct sockaddr_un      sa_un; 
     100        s_config * config = NULL; 
     101        char linebuffer[MAX_BUF]; 
     102        int len = 0; 
     103        char *running1 = NULL; 
     104        char *running2 = NULL; 
     105        char *token1 = NULL; 
     106        char *token2 = NULL; 
     107        char onechar; 
     108        char *command = NULL; 
     109        char *key = NULL; 
     110        char *value = NULL; 
     111        t_client * client = NULL; 
     112        t_client * lastclient = NULL; 
     113 
     114        config = config_get_config(); 
     115         
     116        debug(LOG_INFO, "Connecting to parent to download clients"); 
     117 
     118        /* Connect to socket */ 
     119        sock = socket(AF_UNIX, SOCK_STREAM, 0); 
     120        memset(&sa_un, 0, sizeof(sa_un)); 
     121        sa_un.sun_family = AF_UNIX; 
     122        strncpy(sa_un.sun_path, config->internal_sock, (sizeof(sa_un.sun_path) - 1)); 
     123 
     124        if (connect(sock, (struct sockaddr *)&sa_un, strlen(sa_un.sun_path) + sizeof(sa_un.sun_family))) { 
     125                debug(LOG_ERR, "Failed to connect to parent (%s) - client list not downloaded", strerror(errno)); 
     126                return; 
     127        } 
     128 
     129        debug(LOG_INFO, "Connected to parent.  Downloading clients"); 
     130 
     131        LOCK_CLIENT_LIST(); 
     132 
     133        command = NULL; 
     134        memset(linebuffer, 0, sizeof(linebuffer)); 
     135        len = 0; 
     136        client = NULL; 
     137        /* Get line by line */ 
     138        while (read(sock, &onechar, 1) == 1) { 
     139                if (onechar == '\n') { 
     140                        /* End of line */ 
     141                        onechar = '\0'; 
     142                } 
     143                linebuffer[len++] = onechar; 
     144 
     145                if (!onechar) { 
     146                        /* We have a complete entry in linebuffer - parse it */ 
     147                        debug(LOG_DEBUG, "Received from parent: [%s]", linebuffer); 
     148                        running1 = linebuffer; 
     149                        while ((token1 = strsep(&running1, "|")) != NULL) { 
     150                                if (!command) { 
     151                                        /* The first token is the command */ 
     152                                        command = token1; 
     153                                } 
     154                                else { 
     155                                /* Token1 has something like "foo=bar" */ 
     156                                        running2 = token1; 
     157                                        key = value = NULL; 
     158                                        while ((token2 = strsep(&running2, "=")) != NULL) { 
     159                                                if (!key) { 
     160                                                        key = token2; 
     161                                                } 
     162                                                else if (!value) { 
     163                                                        value = token2; 
     164                                                } 
     165                                        } 
     166                                } 
     167 
     168                                if (strcmp(command, "CLIENT") == 0) { 
     169                                        /* This line has info about a client in the client list */ 
     170                                        if (!client) { 
     171                                                /* Create a new client struct */ 
     172                                                client = safe_malloc(sizeof(t_client)); 
     173                                                memset(client, 0, sizeof(t_client)); 
     174                                        } 
     175                                } 
     176 
     177                                if (key && value) { 
     178                                        if (strcmp(command, "CLIENT") == 0) { 
     179                                                /* Assign the key into the appropriate slot in the connection structure */ 
     180                                                if (strcmp(key, "ip") == 0) { 
     181                                                        client->ip = safe_strdup(value); 
     182                                                } 
     183                                                else if (strcmp(key, "mac") == 0) { 
     184                                                        client->mac = safe_strdup(value); 
     185                                                } 
     186                                                else if (strcmp(key, "token") == 0) { 
     187                                                        client->token = safe_strdup(value); 
     188                                                } 
     189                                                else if (strcmp(key, "fw_connection_state") == 0) { 
     190                                                        client->fw_connection_state = atoi(value); 
     191                                                } 
     192                                                else if (strcmp(key, "fd") == 0) { 
     193                                                        client->fd = atoi(value); 
     194                                                } 
     195                                                else if (strcmp(key, "counters_incoming") == 0) { 
     196                                                        client->counters.incoming_history = atoll(value); 
     197                                                        client->counters.incoming = client->counters.incoming_history; 
     198                                                } 
     199                                                else if (strcmp(key, "counters_outgoing") == 0) { 
     200                                                        client->counters.outgoing_history = atoll(value); 
     201                                                        client->counters.outgoing = client->counters.outgoing_history; 
     202                                                } 
     203                                                else if (strcmp(key, "counters_last_updated") == 0) { 
     204                                                        client->counters.last_updated = atol(value); 
     205                                                } 
     206                                                else { 
     207                                                        debug(LOG_NOTICE, "I don't know how to inherit key [%s] value [%s] from parent", key, value); 
     208                                                } 
     209                                        } 
     210                                } 
     211                        } 
     212 
     213                        /* End of parsing this command */ 
     214                        if (client) { 
     215                                /* Add this client to the client list */ 
     216                                if (!firstclient) { 
     217                                        firstclient = client; 
     218                                        lastclient = firstclient; 
     219                                } 
     220                                else { 
     221                                        lastclient->next = client; 
     222                                        lastclient = client; 
     223                                } 
     224                        } 
     225 
     226                        /* Clean up */ 
     227                        command = NULL; 
     228                        memset(linebuffer, 0, sizeof(linebuffer)); 
     229                        len = 0; 
     230                        client = NULL; 
     231                } 
     232        } 
     233 
     234        UNLOCK_CLIENT_LIST(); 
     235        debug(LOG_INFO, "Client list downloaded successfully from parent"); 
     236 
     237        close(sock); 
     238} 
     239 
    69240/**@internal 
    70241 * @brief Handles SIGCHLD signals to avoid zombie processes 
     
    78249{ 
    79250        int     status; 
     251        pid_t rc; 
    80252         
    81         wait(&status); 
     253        debug(LOG_DEBUG, "Handler for SIGCHLD called. Trying to reap a child"); 
     254 
     255        rc = waitpid(-1, &status, WNOHANG); 
     256 
     257        debug(LOG_DEBUG, "Handler for SIGCHLD reaped child PID %d", rc); 
    82258} 
    83259 
     
    89265        static  pthread_mutex_t sigterm_mutex = PTHREAD_MUTEX_INITIALIZER; 
    90266 
    91         debug(LOG_INFO, "Caught signal %d", s); 
     267        debug(LOG_INFO, "Handler for termination caught signal %d", s); 
    92268 
    93269        /* Makes sure we only call fw_destroy() once. */ 
     
    100276        } 
    101277 
    102         debug(LOG_DEBUG, "Flushing firewall rules..."); 
     278        debug(LOG_INFO, "Flushing firewall rules..."); 
    103279        fw_destroy(); 
    104280 
     
    116292        } 
    117293 
    118         debug(LOG_DEBUG, "Exiting..."); 
     294        debug(LOG_NOTICE, "Exiting..."); 
    119295        exit(s == 0 ? 1 : 0); 
    120296} 
     
    179355main_loop(void) 
    180356{ 
    181         httpd * webserver; 
    182357        int result; 
    183358        pthread_t       tid; 
     
    186361        void **params; 
    187362 
    188         /* Initializes the linked list of connected clients */ 
    189         client_list_init(); 
    190  
    191363    /* If we don't have the Gateway IP address, get it. Can't fail. */ 
    192364    if (!config->gw_address) { 
     
    194366        if ((config->gw_address = get_iface_ip(config->gw_interface)) == NULL) { 
    195367                    debug(LOG_ERR, "Could not get IP address information of %s, exiting...", config->gw_interface); 
    196             exit(1); 
     368                       exit(1); 
    197369        } 
    198370        debug(LOG_DEBUG, "%s = %s", config->gw_interface, config->gw_address); 
     
    200372 
    201373        /* Initializes the web server */ 
    202         debug(LOG_NOTICE, "Creating web server on %s:%d",  
    203                         config->gw_address, config->gw_port); 
    204         webserver = httpdCreate(config->gw_address, config->gw_port); 
    205         if (webserver == NULL) { 
    206                 debug(LOG_ERR, "Could not create web server: %s", 
    207                                 strerror(errno)); 
     374        debug(LOG_NOTICE, "Creating web server on %s:%d", config->gw_address, config->gw_port); 
     375        if ((webserver = httpdCreate(config->gw_address, config->gw_port)) == NULL) { 
     376                debug(LOG_ERR, "Could not create web server: %s", strerror(errno)); 
    208377                exit(1); 
    209378        } 
     379 
    210380        debug(LOG_DEBUG, "Assigning callbacks to web server"); 
    211381        httpdAddCContent(webserver, "/", "wifidog", 0, NULL, http_callback_wifidog); 
     
    216386        httpdAddC404Content(webserver, http_callback_404); 
    217387 
    218         /* Init the signals to catch chld/quit/etc */ 
    219         init_signals(); 
    220  
    221388        /* Reset the firewall (if WiFiDog crashed) */ 
    222389        fw_destroy(); 
     390        /* Then initialize it */ 
    223391        fw_init(); 
    224392 
     
    270438                         * We got a connection 
    271439                         * 
    272                          * We should fork another thread 
     440                         * We should create another thread 
    273441                         */ 
    274442                        debug(LOG_INFO, "Received connection from %s, spawning worker thread", r->clientAddr); 
     
    297465 
    298466/** Reads the configuration file and then starts the main loop */ 
    299 int 
    300 main(int argc, char **argv) 
    301 
     467int main(int argc, char **argv) { 
     468 
    302469        s_config *config = config_get_config(); 
    303470        config_init(); 
     
    305472        parse_commandline(argc, argv); 
    306473 
     474        /* Initialize the config */ 
    307475        config_read(config->configfile); 
    308476        config_validate(); 
    309477 
     478        /* Initializes the linked list of connected clients */ 
     479        client_list_init(); 
     480 
     481        /* Init the signals to catch chld/quit/etc */ 
     482        init_signals(); 
     483 
     484        if (restarted) { 
     485                /* 
     486                 * We were restarted and our parent is waiting for us to talk to it over the socket 
     487                 */ 
     488                get_clients_from_parent(); 
     489 
     490                /* 
     491                 * At this point the parent will start destroying itself and the firewall. Let it finish it's job before we continue 
     492                 */ 
     493                while (kill(restarted, 0) != -1) { 
     494                        debug(LOG_INFO, "Waiting for parent PID %d to die before continuing loading", restarted); 
     495                        sleep(1); 
     496                } 
     497 
     498                debug(LOG_INFO, "Parent PID %d seems to be dead. Continuing loading."); 
     499        } 
     500 
    310501        if (config->daemon) { 
    311502 
    312503                debug(LOG_INFO, "Forking into background"); 
    313504 
    314                 switch(fork()) { 
    315                 case -1: /* error */ 
    316                         debug(LOG_ERR, "fork(): %s", strerror(errno)); 
    317                         exit(1); 
    318                         break; 
    319  
    320                 case 0: /* parent */ 
    321                         main_loop(); 
    322                         break; 
    323  
    324                 default: /* child */ 
    325                         exit(0); 
    326                         break; 
    327                 } 
    328         } else { 
     505                switch(safe_fork()) { 
     506                        case 0: /* child */ 
     507                                setsid(); 
     508                                append_x_restartargv(); 
     509                                main_loop(); 
     510                                break; 
     511 
     512                        default: /* parent */ 
     513                                exit(0); 
     514                                break; 
     515                } 
     516        } 
     517        else { 
     518                append_x_restartargv(); 
    329519                main_loop(); 
    330520        } 
  • branches/wdctlrestart/wifidog/src/safe.c

    r467 r644  
    2828 */ 
    2929 
     30 
    3031#include <stdarg.h> 
     32#include <stdio.h> 
    3133#include <stdlib.h> 
    3234#include <string.h> 
    3335#include <errno.h> 
    3436 
     37#include "httpd.h" 
    3538#include "safe.h" 
    3639#include "debug.h" 
    3740#include <syslog.h> 
     41 
     42/* From gateway.c */ 
     43extern httpd * webserver; 
    3844 
    3945void * safe_malloc (size_t size) { 
     
    8389        return (retval); 
    8490} 
     91 
     92pid_t safe_fork(void) { 
     93        pid_t result; 
     94        result = fork(); 
     95 
     96        if (result == -1) { 
     97                debug(LOG_CRIT, "Failed to fork: %s.  Bailing out", strerror(errno)); 
     98                exit (1); 
     99        } 
     100        else if (result == 0) { 
     101                /* I'm the child - do some cleanup */ 
     102                if (webserver) { 
     103                        close(webserver->serverSock); 
     104                        webserver = NULL; 
     105                } 
     106        } 
     107 
     108        return result; 
     109} 
     110 
  • branches/wdctlrestart/wifidog/src/safe.h

    r467 r644  
    2929 
    3030#include <stdarg.h> /* For va_list */ 
     31#include <sys/types.h> /* For fork */ 
     32#include <unistd.h> /* For fork */ 
    3133 
    3234/** @brief Safe version of malloc 
     
    4648int safe_vasprintf(char **strp, const char *fmt, va_list ap); 
    4749 
     50/* @brief Safe version of fork 
     51 */ 
     52 
     53pid_t safe_fork(void); 
     54 
    4855#endif /* _SAFE_H_ */ 
    4956 
  • branches/wdctlrestart/wifidog/src/util.c

    r493 r644  
    6565extern  pthread_mutex_t config_mutex; 
    6666 
     67/* Defined in commandline.c */ 
     68extern pid_t restarted; 
     69 
    6770/* XXX Do these need to be locked ? */ 
    6871static time_t last_online_time = 0; 
     
    8992    new_argv[3] = NULL; 
    9093 
    91     if ((pid = fork()) < 0) {    /* fork a child process           */ 
    92         debug(LOG_ERR, "fork(): %s", strerror(errno)); 
    93         exit(1); 
    94     } else if (pid == 0) {    /* for the child process:         */ 
     94         pid = safe_fork(); 
     95         if (pid == 0) {    /* for the child process:         */ 
    9596&n