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

(-)mod_cgid.c (+93 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"
39
#include "apr_thread_proc.h"
40
#include "apr_thread_mutex.h"
38
41
39
#define APR_WANT_STRFUNC
42
#define APR_WANT_STRFUNC
40
#include "apr_want.h"
43
#include "apr_want.h"
Lines 185-190 Link Here
185
    int loglevel; /* to stuff in server_rec */
188
    int loglevel; /* to stuff in server_rec */
186
} cgid_req_t;
189
} cgid_req_t;
187
190
191
192
#define EXPIRE_CHECK_INTERVAL 15L * 1000L * 1000L
193
static apr_hash_t *cgi_pid_hash;
194
static apr_thread_mutex_t *cgi_pid_lock;
195
static apr_time_t cgi_timeout;
196
188
/* This routine is called to create the argument list to be passed
197
/* 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
198
 * 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
199
 * group are the first three arguments to be passed; if not, all three
Lines 564-569 Link Here
564
    ap_log_error(APLOG_MARK, APLOG_ERR, err, r->server, "%s", description);
573
    ap_log_error(APLOG_MARK, APLOG_ERR, err, r->server, "%s", description);
565
}
574
}
566
575
576
static void cgiwatcher_add(pid_t pid, apr_pool_t *pool) {
577
    pid_t *key = apr_palloc(pool, sizeof(pid_t));
578
    memcpy(key, &pid, sizeof(pid_t));
579
580
    apr_time_t *val = apr_palloc(pool, sizeof(apr_time_t));
581
    /* when the timeout will happen*/
582
    apr_time_t last = apr_time_now() + cgi_timeout;
583
    memcpy(val, &last, sizeof(apr_time_t));
584
585
    apr_thread_mutex_lock(cgi_pid_lock);
586
    apr_hash_set(cgi_pid_hash, key, sizeof(apr_time_t),val);
587
    apr_thread_mutex_unlock(cgi_pid_lock);
588
}
589
590
static void cgiwatcher_remove(pid_t pid) {
591
    apr_thread_mutex_lock(cgi_pid_lock);
592
    /* TODO: How does the key and value allocated get reclaimed? */
593
    apr_hash_set(cgi_pid_hash, &pid, 0, (void*)0);
594
    apr_thread_mutex_unlock(cgi_pid_lock);
595
}
596
597
static void check_child(pid_t pid, apr_time_t time, apr_pool_t *pool) {
598
    apr_time_t rem = time - apr_time_now();
599
    ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, pool, "cgiwatcher: on the loop for cgi [%d] (%d)", pid, apr_time_sec(rem));
600
601
    if (time < apr_time_now()) { /* timed out..*/
602
        ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, pool, "cgiwatcher: killed cgi [%d]", pid);
603
        kill(pid, SIGHUP);
604
    }
605
}
606
607
static void * APR_THREAD_FUNC cgiwatcher(apr_thread_t *thd, void *data)
608
{
609
    apr_hash_index_t *hi;
610
    apr_pool_t *pool_iter;
611
    apr_pool_create(&pool_iter, pcgi);
612
    while(!daemon_should_exit) {
613
        apr_thread_mutex_lock(cgi_pid_lock);
614
        for (hi = apr_hash_first(pool_iter, cgi_pid_hash); hi; hi = apr_hash_next(hi)) {
615
            pid_t *key;
616
            apr_ssize_t len;
617
            apr_time_t *val;
618
            apr_hash_this(hi, (void*)&key, &len, (void*)&val);
619
            if (!val) continue;
620
            check_child(*key, *val, pool_iter);
621
            /* cleanup script will take out the entry from the hash.*/
622
        }
623
        apr_thread_mutex_unlock(cgi_pid_lock);
624
        apr_pool_clear(pool_iter);
625
        apr_sleep(EXPIRE_CHECK_INTERVAL);
626
    }
627
}
628
629
static apr_status_t setup_timeout_thread(apr_pool_t *pool)
630
{
631
    apr_thread_mutex_create(&cgi_pid_lock, APR_THREAD_MUTEX_DEFAULT, pcgi);
632
    cgi_pid_hash = apr_hash_make(pcgi);
633
    apr_thread_t *timeout_thread;
634
    return apr_thread_create(&timeout_thread, NULL, cgiwatcher, pcgi, pcgi);
635
}
636
567
static int cgid_server(void *data)
637
static int cgid_server(void *data)
568
{
638
{
569
    struct sockaddr_un unix_addr;
639
    struct sockaddr_un unix_addr;
Lines 631-636 Link Here
631
            return errno;
701
            return errno;
632
        }
702
        }
633
    }
703
    }
704
    
705
    /* Set up the thread to watch for timeout */
706
    rv = setup_timeout_thread(pcgi);
707
    if(rv != APR_SUCCESS) {
708
        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, main_server,
709
                "Couldn't start the cgiwatcher thread.");
710
        return rv;
711
    }
634
712
635
    unixd_setup_child(); /* if running as root, switch to configured user/group */
713
    unixd_setup_child(); /* if running as root, switch to configured user/group */
636
714
Lines 700-705 Link Here
700
                             "Error writing pid %" APR_PID_T_FMT " to handler", pid);
778
                             "Error writing pid %" APR_PID_T_FMT " to handler", pid);
701
            }
779
            }
702
            close(sd2);
780
            close(sd2);
781
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
782
                             main_server,
783
                             "cgiwatcher: remove pid from list %d", pid);
784
785
            /* GETPID request is initiated by the cleanup script which means the pid is no longer alive.*/
786
            cgiwatcher_remove(pid);
703
            continue;
787
            continue;
704
        }
788
        }
705
789
Lines 782-787 Link Here
782
                             apr_filepath_name_get(r->filename));
866
                             apr_filepath_name_get(r->filename));
783
867
784
                procnew->pid = 0; /* no process to clean up */
868
                procnew->pid = 0; /* no process to clean up */
869
            } else {
870
                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
871
                             "cgiwatcher: Adding process to timeout list: %d: %s", procnew->pid,
872
                             apr_filepath_name_get(r->filename));
873
                cgiwatcher_add(procnew->pid, pcgi);
785
            }
874
            }
786
        }
875
        }
787
876
Lines 818-823 Link Here
818
{
907
{
819
908
820
    daemon_should_exit = 0; /* clear setting from previous generation */
909
    daemon_should_exit = 0; /* clear setting from previous generation */
910
    cgi_timeout = main_server->timeout;
911
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server,
912
                 "cgiwatcher: timeout - %" APR_TIME_T_FMT ".", main_server->timeout);
913
821
    if ((daemon_pid = fork()) < 0) {
914
    if ((daemon_pid = fork()) < 0) {
822
        ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,
915
        ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,
823
                     "mod_cgid: Couldn't spawn cgid daemon process");
916
                     "mod_cgid: Couldn't spawn cgid daemon process");

Return to bug 43494