Changeset 1546 for zzuf


Ignore:
Timestamp:
Jan 3, 2007, 9:43:47 PM (14 years ago)
Author:
Sam Hocevar
Message:
  • Split some code into clean functions.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • zzuf/trunk/src/zzuf.c

    r1544 r1546  
    4242
    4343static void spawn_child(char **);
     44static void clean_children(void);
     45static void read_children(void);
     46
    4447static char *merge_regex(char *, char *);
    4548static char *merge_file(char *, char *);
     
    5053#endif
    5154
    52 struct child_list
     55static struct child_list
    5356{
    5457    enum status
     
    6669    time_t date;
    6770} *child_list;
    68 int parallel = 1, child_count = 0;
    69 
    70 int seed = 0;
    71 int endseed = 1;
     71static int parallel = 1, child_count = 0;
     72
     73static int seed = 0;
     74static int endseed = 1;
     75static int quiet = 0;
     76static int maxbytes = -1;
     77static double maxtime = -1.0;
    7278
    7379#define ZZUF_FD_SET(fd, p_fdset, maxfd) \
     
    8692    char **newargv;
    8793    char *parser, *include = NULL, *exclude = NULL;
    88     int i, j, quiet = 0, maxbytes = -1, cmdline = 0;
    89     double maxtime = -1.0;
     94    int i, cmdline = 0;
    9095
    9196#if defined(HAVE_GETOPT_H)
     
    236241    while(child_count || seed < endseed)
    237242    {
    238         struct timeval tv;
    239         time_t now = time(NULL);
    240         fd_set fdset;
    241         int ret, maxfd = 0;
    242 
    243         /* Spawn a new child, if necessary */
     243        /* Spawn one new child, if necessary */
    244244        if(child_count < parallel && seed < endseed)
    245245            spawn_child(newargv);
    246246
    247         /* Terminate children if necessary */
    248         for(i = 0; i < parallel; i++)
    249         {
    250             if(child_list[i].status == STATUS_RUNNING
    251                 && maxbytes >= 0 && child_list[i].bytes > maxbytes)
    252             {
    253                 fprintf(stdout, "seed %i: data exceeded, sending SIGTERM\n",
    254                         child_list[i].seed);
    255                 kill(child_list[i].pid, SIGTERM);
    256                 child_list[i].date = now;
    257                 child_list[i].status = STATUS_SIGTERM;
    258             }
    259 
    260             if(child_list[i].status == STATUS_RUNNING
    261                 && maxtime >= 0.0
    262                 && difftime(now, child_list[i].date) > maxtime)
    263             {
    264                 fprintf(stdout, "seed %i: time exceeded, sending SIGTERM\n",
    265                         child_list[i].seed);
    266                 kill(child_list[i].pid, SIGTERM);
    267                 child_list[i].date = now;
    268                 child_list[i].status = STATUS_SIGTERM;
    269             }
    270         }
    271 
    272         /* Kill children if necessary */
    273         for(i = 0; i < parallel; i++)
    274         {
    275             if(child_list[i].status == STATUS_SIGTERM
    276                 && difftime(now, child_list[i].date) > 2.0)
    277             {
    278                 fprintf(stdout, "seed %i: not responding, sending SIGKILL\n",
    279                         child_list[i].seed);
    280                 kill(child_list[i].pid, SIGKILL);
    281                 child_list[i].status = STATUS_SIGKILL;
    282             }
    283         }
    284 
    285         /* Collect dead children */
    286         for(i = 0; i < parallel; i++)
    287         {
    288             int status;
    289             pid_t pid;
    290 
    291             if(child_list[i].status != STATUS_SIGKILL
    292                 && child_list[i].status != STATUS_SIGTERM
    293                 && child_list[i].status != STATUS_EOF)
    294                 continue;
    295 
    296             pid = waitpid(child_list[i].pid, &status, WNOHANG);
    297             if(pid <= 0)
    298                 continue;
    299 
    300             if(WIFEXITED(status) && WEXITSTATUS(status))
    301                 fprintf(stdout, "seed %i: exit %i\n",
    302                         child_list[i].seed, WEXITSTATUS(status));
    303             else if(WIFSIGNALED(status))
    304                 fprintf(stdout, "seed %i: signal %i\n",
    305                         child_list[i].seed, WTERMSIG(status));
    306 
    307             for(j = 0; j < 3; j++)
    308                 if(child_list[i].fd[j] >= 0)
    309                     close(child_list[i].fd[j]);
    310 
    311             child_list[i].status = STATUS_FREE;
    312             child_count--;
    313         }
    314 
    315         fflush(stdout);
    316 
    317         /* Read data from all sockets */
    318         FD_ZERO(&fdset);
    319         for(i = 0; i < parallel; i++)
    320         {
    321             if(child_list[i].status != STATUS_RUNNING)
    322                 continue;
    323 
    324             for(j = 0; j < 3; j++)
    325                 ZZUF_FD_SET(child_list[i].fd[j], &fdset, maxfd);
    326         }
    327         tv.tv_sec = 0;
    328         tv.tv_usec = 1000;
    329 
    330         ret = select(maxfd + 1, &fdset, NULL, NULL, &tv);
    331         if(ret < 0)
    332             perror("select");
    333         if(ret <= 0)
    334             continue;
    335 
    336         /* XXX: cute (i, j) iterating hack */
    337         for(i = 0, j = 0; i < parallel; i += (j == 2), j = (j + 1) % 3)
    338         {
    339             char buf[BUFSIZ];
    340 
    341             if(child_list[i].status != STATUS_RUNNING)
    342                 continue;
    343 
    344             if(!ZZUF_FD_ISSET(child_list[i].fd[j], &fdset))
    345                 continue;
    346 
    347             ret = read(child_list[i].fd[j], buf, BUFSIZ - 1);
    348             if(ret > 0)
    349             {
    350                 /* We got data */
    351                 if(j != 0)
    352                     child_list[i].bytes += ret;
    353                 if(!quiet || j == 0)
    354                     write((j < 2) ? STDERR_FILENO : STDOUT_FILENO, buf, ret);
    355             }
    356             else if(ret == 0)
    357             {
    358                 /* End of file reached */
    359                 close(child_list[i].fd[j]);
    360                 child_list[i].fd[j] = -1;
    361 
    362                 if(child_list[i].fd[0] == -1 && child_list[i].fd[1] == -1
    363                    && child_list[i].fd[2] == -1)
    364                     child_list[i].status = STATUS_EOF;
    365             }
    366         }
     247        /* Cleanup dead or dying children */
     248        clean_children();
     249
     250        /* Read data from children */
     251        read_children();
    367252    }
    368253
     
    481366            seed++;
    482367            break;
     368    }
     369}
     370
     371static void clean_children(void)
     372{
     373    time_t now = time(NULL);
     374    int i, j;
     375
     376    /* Terminate children if necessary */
     377    for(i = 0; i < parallel; i++)
     378    {
     379        if(child_list[i].status == STATUS_RUNNING
     380            && maxbytes >= 0 && child_list[i].bytes > maxbytes)
     381        {
     382            fprintf(stdout, "seed %i: data exceeded, sending SIGTERM\n",
     383                    child_list[i].seed);
     384            kill(child_list[i].pid, SIGTERM);
     385            child_list[i].date = now;
     386            child_list[i].status = STATUS_SIGTERM;
     387        }
     388
     389        if(child_list[i].status == STATUS_RUNNING
     390            && maxtime >= 0.0
     391            && difftime(now, child_list[i].date) > maxtime)
     392        {
     393            fprintf(stdout, "seed %i: time exceeded, sending SIGTERM\n",
     394                    child_list[i].seed);
     395            kill(child_list[i].pid, SIGTERM);
     396            child_list[i].date = now;
     397            child_list[i].status = STATUS_SIGTERM;
     398        }
     399    }
     400
     401    /* Kill children if necessary */
     402    for(i = 0; i < parallel; i++)
     403    {
     404        if(child_list[i].status == STATUS_SIGTERM
     405            && difftime(now, child_list[i].date) > 2.0)
     406        {
     407            fprintf(stdout, "seed %i: not responding, sending SIGKILL\n",
     408                    child_list[i].seed);
     409            kill(child_list[i].pid, SIGKILL);
     410            child_list[i].status = STATUS_SIGKILL;
     411        }
     412    }
     413
     414    /* Collect dead children */
     415    for(i = 0; i < parallel; i++)
     416    {
     417        int status;
     418        pid_t pid;
     419
     420        if(child_list[i].status != STATUS_SIGKILL
     421            && child_list[i].status != STATUS_SIGTERM
     422            && child_list[i].status != STATUS_EOF)
     423            continue;
     424
     425        pid = waitpid(child_list[i].pid, &status, WNOHANG);
     426        if(pid <= 0)
     427            continue;
     428
     429        if(WIFEXITED(status) && WEXITSTATUS(status))
     430            fprintf(stdout, "seed %i: exit %i\n",
     431                    child_list[i].seed, WEXITSTATUS(status));
     432        else if(WIFSIGNALED(status))
     433            fprintf(stdout, "seed %i: signal %i\n",
     434                    child_list[i].seed, WTERMSIG(status));
     435
     436        for(j = 0; j < 3; j++)
     437            if(child_list[i].fd[j] >= 0)
     438                close(child_list[i].fd[j]);
     439
     440        child_list[i].status = STATUS_FREE;
     441        child_count--;
     442    }
     443
     444    fflush(stdout);
     445}
     446
     447static void read_children(void)
     448{
     449    struct timeval tv;
     450    fd_set fdset;
     451    int i, j, ret, maxfd = 0;
     452
     453    /* Read data from all sockets */
     454    FD_ZERO(&fdset);
     455    for(i = 0; i < parallel; i++)
     456    {
     457        if(child_list[i].status != STATUS_RUNNING)
     458            continue;
     459
     460        for(j = 0; j < 3; j++)
     461            ZZUF_FD_SET(child_list[i].fd[j], &fdset, maxfd);
     462    }
     463    tv.tv_sec = 0;
     464    tv.tv_usec = 1000;
     465
     466    ret = select(maxfd + 1, &fdset, NULL, NULL, &tv);
     467    if(ret < 0)
     468        perror("select");
     469    if(ret <= 0)
     470        return;
     471
     472    /* XXX: cute (i, j) iterating hack */
     473    for(i = 0, j = 0; i < parallel; i += (j == 2), j = (j + 1) % 3)
     474    {
     475        char buf[BUFSIZ];
     476
     477        if(child_list[i].status != STATUS_RUNNING)
     478            continue;
     479
     480        if(!ZZUF_FD_ISSET(child_list[i].fd[j], &fdset))
     481            continue;
     482
     483        ret = read(child_list[i].fd[j], buf, BUFSIZ - 1);
     484        if(ret > 0)
     485        {
     486            /* We got data */
     487            if(j != 0)
     488                child_list[i].bytes += ret;
     489            if(!quiet || j == 0)
     490                write((j < 2) ? STDERR_FILENO : STDOUT_FILENO, buf, ret);
     491        }
     492        else if(ret == 0)
     493        {
     494            /* End of file reached */
     495            close(child_list[i].fd[j]);
     496            child_list[i].fd[j] = -1;
     497
     498            if(child_list[i].fd[0] == -1 && child_list[i].fd[1] == -1
     499               && child_list[i].fd[2] == -1)
     500                child_list[i].status = STATUS_EOF;
     501        }
    483502    }
    484503}
Note: See TracChangeset for help on using the changeset viewer.