View | Details | Raw Unified | Return to bug 43494
Collapse All | Expand All

(-)mod_cgid.c (-3 / +87 lines)
Lines 35-40 Link Here
35
#include "apr_buckets.h"
35
#include "apr_buckets.h"
36
#include "apr_optional.h"
36
#include "apr_optional.h"
37
#include "apr_signal.h"
37
#include "apr_signal.h"
38
#include "apr_time.h"
38
39
39
#define APR_WANT_STRFUNC
40
#define APR_WANT_STRFUNC
40
#include "apr_want.h"
41
#include "apr_want.h"
Lines 185-190 Link Here
185
    int loglevel; /* to stuff in server_rec */
186
    int loglevel; /* to stuff in server_rec */
186
} cgid_req_t;
187
} cgid_req_t;
187
188
189
#define TIMEOUT_ALARM 15
190
191
static apr_hash_t *cgi_pid_hash;
192
static apr_time_t cgi_timeout;
193
static int cgi_enable_timeout_alarm = 0;
194
188
/* This routine is called to create the argument list to be passed
195
/* This routine is called to create the argument list to be passed
189
 * to the CGI script.  When suexec is enabled, the suexec path, user, and
196
 * to the CGI script.  When suexec is enabled, the suexec path, user, and
190
 * group are the first three arguments to be passed; if not, all three
197
 * group are the first three arguments to be passed; if not, all three
Lines 541-550 Link Here
541
    return APR_SUCCESS;
548
    return APR_SUCCESS;
542
}
549
}
543
550
551
static void cgiwatcher_add(pid_t pid, apr_pool_t *pool) {
552
    pid_t *key = apr_palloc(pool, sizeof(pid_t));
553
    memcpy(key, &pid, sizeof(pid_t));
554
555
    apr_time_t *val = apr_palloc(pool, sizeof(apr_time_t));
556
    /* when the timeout will happen*/
557
    apr_time_t last = apr_time_now() + cgi_timeout;
558
    memcpy(val, &last, sizeof(apr_time_t));
559
560
    apr_hash_set(cgi_pid_hash, key, sizeof(apr_time_t),val);
561
}
562
563
static void cgiwatcher_remove(pid_t pid) {
564
    /* TODO: How does the key and value allocated get reclaimed? */
565
    apr_hash_set(cgi_pid_hash, &pid, 0, (void*)0);
566
}
567
568
static void check_child(pid_t pid, apr_time_t time, apr_pool_t *pool) {
569
    apr_time_t rem = time - apr_time_now();
570
    ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, pool, "cgiwatcher: on the loop for cgi [%d] (%d)", pid, apr_time_sec(rem));
571
572
    if (time < apr_time_now()) { /* timed out..*/
573
        ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, pool, "cgiwatcher: killed cgi [%d]", pid);
574
        kill(pid, SIGHUP);
575
    }
576
}
577
578
static void check_timeouts(apr_pool_t* pool)
579
{   
580
    if(cgi_enable_timeout_alarm) {
581
        /* Only meddle with apr_hash if we are reasonably sure that no one else is.*/
582
        ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, pool, "cgiwatcher: checking timeouts");
583
        apr_hash_index_t *hi;
584
        for (hi = apr_hash_first(pool, cgi_pid_hash); hi; hi = apr_hash_next(hi)) {
585
            pid_t *key;
586
            apr_ssize_t len;
587
            apr_time_t *val;
588
            apr_hash_this(hi, (void*)&key, &len, (void*)&val);
589
            if (!val) continue;
590
            check_child(*key, *val, pool);
591
            /* cleanup script will take out the entry from the hash.*/
592
        }
593
    }
594
    /* Setup the next call */
595
    alarm((unsigned long)TIMEOUT_ALARM);
596
}
597
544
static void daemon_signal_handler(int sig)
598
static void daemon_signal_handler(int sig)
545
{
599
{
546
    if (sig == SIGHUP) {
600
    switch (sig) {
547
        ++daemon_should_exit;
601
        case SIGHUP:
602
            ++daemon_should_exit;
603
            break;
604
        case SIGALRM:
605
            check_timeouts(pcgi);
606
            break;
548
    }
607
    }
549
}
608
}
550
609
Lines 579-584 Link Here
579
638
580
    apr_signal(SIGCHLD, SIG_IGN);
639
    apr_signal(SIGCHLD, SIG_IGN);
581
    apr_signal(SIGHUP, daemon_signal_handler);
640
    apr_signal(SIGHUP, daemon_signal_handler);
641
    apr_signal(SIGALRM, daemon_signal_handler);
582
642
583
    /* Close our copy of the listening sockets */
643
    /* Close our copy of the listening sockets */
584
    ap_close_listeners();
644
    ap_close_listeners();
Lines 631-639 Link Here
631
            return errno;
691
            return errno;
632
        }
692
        }
633
    }
693
    }
634
694
    
635
    unixd_setup_child(); /* if running as root, switch to configured user/group */
695
    unixd_setup_child(); /* if running as root, switch to configured user/group */
696
    
697
    cgi_pid_hash = apr_hash_make(pcgi);
636
698
699
    /* set alarm up for cgiwatcher */
700
    alarm((unsigned long)TIMEOUT_ALARM);
701
637
    while (!daemon_should_exit) {
702
    while (!daemon_should_exit) {
638
        int errfileno = STDERR_FILENO;
703
        int errfileno = STDERR_FILENO;
639
        char *argv0;
704
        char *argv0;
Lines 654-660 Link Here
654
        apr_pool_clear(ptrans);
719
        apr_pool_clear(ptrans);
655
720
656
        len = sizeof(unix_addr);
721
        len = sizeof(unix_addr);
722
723
        /* unlock for alarm to run check_timeout */
724
        cgi_enable_timeout_alarm = 1;
657
        sd2 = accept(sd, (struct sockaddr *)&unix_addr, &len);
725
        sd2 = accept(sd, (struct sockaddr *)&unix_addr, &len);
726
        cgi_enable_timeout_alarm = 0;
658
        if (sd2 < 0) {
727
        if (sd2 < 0) {
659
#if defined(ENETDOWN)
728
#if defined(ENETDOWN)
660
            if (errno == ENETDOWN) {
729
            if (errno == ENETDOWN) {
Lines 700-705 Link Here
700
                             "Error writing pid %" APR_PID_T_FMT " to handler", pid);
769
                             "Error writing pid %" APR_PID_T_FMT " to handler", pid);
701
            }
770
            }
702
            close(sd2);
771
            close(sd2);
772
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
773
                             main_server,
774
                             "cgiwatcher: remove pid from list %d", pid);
775
776
            /* GETPID request is initiated by the cleanup script which means the pid is no longer alive.*/
777
            cgiwatcher_remove(pid);
703
            continue;
778
            continue;
704
        }
779
        }
705
780
Lines 782-787 Link Here
782
                             apr_filepath_name_get(r->filename));
857
                             apr_filepath_name_get(r->filename));
783
858
784
                procnew->pid = 0; /* no process to clean up */
859
                procnew->pid = 0; /* no process to clean up */
860
            } else {
861
                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
862
                             "cgiwatcher: Adding process to timeout list: %d: %s", procnew->pid,
863
                             apr_filepath_name_get(r->filename));
864
                cgiwatcher_add(procnew->pid, pcgi);
785
            }
865
            }
786
        }
866
        }
787
867
Lines 818-823 Link Here
818
{
898
{
819
899
820
    daemon_should_exit = 0; /* clear setting from previous generation */
900
    daemon_should_exit = 0; /* clear setting from previous generation */
901
    cgi_timeout = main_server->timeout;
902
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server,
903
                 "cgiwatcher: timeout - %" APR_TIME_T_FMT ".", main_server->timeout);
904
821
    if ((daemon_pid = fork()) < 0) {
905
    if ((daemon_pid = fork()) < 0) {
822
        ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,
906
        ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,
823
                     "mod_cgid: Couldn't spawn cgid daemon process");
907
                     "mod_cgid: Couldn't spawn cgid daemon process");

Return to bug 43494