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"); |