summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am6
-rw-r--r--src/Makefile.in18
-rw-r--r--src/configparser.c97
-rw-r--r--src/configparser.y1
-rw-r--r--src/connections.c5
-rw-r--r--src/http_auth.c6
-rw-r--r--src/lighttpd-angel.c154
-rw-r--r--src/mod_fastcgi.c89
-rw-r--r--src/mod_mysql_vhost.c2
-rw-r--r--src/server.c84
10 files changed, 357 insertions, 105 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 3af10c8..24967c8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,12 +1,14 @@
AM_CFLAGS = $(FAM_CFLAGS)
noinst_PROGRAMS=proc_open lemon # simple-fcgi #graphic evalo bench ajp ssl error_test adserver gen-license
-sbin_PROGRAMS=lighttpd
+sbin_PROGRAMS=lighttpd lighttpd-angel
bin_PROGRAMS=spawn-fcgi
LEMON=$(top_builddir)/src/lemon
lemon_SOURCES=lemon.c
+lighttpd_angel_SOURCES=lighttpd-angel.c
+
#simple_fcgi_SOURCES=simple-fcgi.c
#simple_fcgi_LDADD=-lfcgi
@@ -254,7 +256,7 @@ hdr = server.h buffer.h network.h log.h keyvalue.h \
splaytree.h proc_open.h status_counter.h \
mod_magnet_cache.h
-DEFS= @DEFS@ -DLIBRARY_DIR="\"$(libdir)\""
+DEFS= @DEFS@ -DLIBRARY_DIR="\"$(libdir)\"" -DSBIN_DIR="\"$(sbindir)\""
lighttpd_SOURCES = $(src)
lighttpd_LDADD = $(PCRE_LIB) $(DL_LIB) $(SENDFILE_LIB) $(ATTR_LIB) $(common_libadd) $(SSL_LIB) $(FAM_LIBS)
diff --git a/src/Makefile.in b/src/Makefile.in
index 3d8194a..2952518 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -36,7 +36,7 @@ build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
noinst_PROGRAMS = proc_open$(EXEEXT) lemon$(EXEEXT)
-sbin_PROGRAMS = lighttpd$(EXEEXT)
+sbin_PROGRAMS = lighttpd$(EXEEXT) lighttpd-angel$(EXEEXT)
bin_PROGRAMS = spawn-fcgi$(EXEEXT)
# if the linker doesn't allow referencing symbols of the binary
@@ -373,6 +373,9 @@ lighttpd_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
lighttpd_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(lighttpd_LDFLAGS) \
$(LDFLAGS) -o $@
+am_lighttpd_angel_OBJECTS = lighttpd-angel.$(OBJEXT)
+lighttpd_angel_OBJECTS = $(am_lighttpd_angel_OBJECTS)
+lighttpd_angel_LDADD = $(LDADD)
am_proc_open_OBJECTS = proc_open-proc_open.$(OBJEXT) \
proc_open-buffer.$(OBJEXT)
proc_open_OBJECTS = $(am_proc_open_OBJECTS)
@@ -409,7 +412,8 @@ SOURCES = $(liblightcomp_la_SOURCES) $(mod_access_la_SOURCES) \
$(mod_status_la_SOURCES) $(mod_trigger_b4_dl_la_SOURCES) \
$(mod_userdir_la_SOURCES) $(mod_usertrack_la_SOURCES) \
$(mod_webdav_la_SOURCES) $(lemon_SOURCES) $(lighttpd_SOURCES) \
- $(proc_open_SOURCES) $(spawn_fcgi_SOURCES)
+ $(lighttpd_angel_SOURCES) $(proc_open_SOURCES) \
+ $(spawn_fcgi_SOURCES)
DIST_SOURCES = $(am__liblightcomp_la_SOURCES_DIST) \
$(mod_access_la_SOURCES) $(mod_accesslog_la_SOURCES) \
$(mod_alias_la_SOURCES) $(mod_auth_la_SOURCES) \
@@ -428,7 +432,8 @@ DIST_SOURCES = $(am__liblightcomp_la_SOURCES_DIST) \
$(mod_trigger_b4_dl_la_SOURCES) $(mod_userdir_la_SOURCES) \
$(mod_usertrack_la_SOURCES) $(mod_webdav_la_SOURCES) \
$(lemon_SOURCES) $(am__lighttpd_SOURCES_DIST) \
- $(proc_open_SOURCES) $(spawn_fcgi_SOURCES)
+ $(lighttpd_angel_SOURCES) $(proc_open_SOURCES) \
+ $(spawn_fcgi_SOURCES)
HEADERS = $(noinst_HEADERS)
ETAGS = etags
CTAGS = ctags
@@ -453,7 +458,7 @@ CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@ -DLIBRARY_DIR="\"$(libdir)\""
+DEFS = @DEFS@ -DLIBRARY_DIR="\"$(libdir)\"" -DSBIN_DIR="\"$(sbindir)\""
DEPDIR = @DEPDIR@
DL_LIB = @DL_LIB@
ECHO = @ECHO@
@@ -573,6 +578,7 @@ top_srcdir = @top_srcdir@
AM_CFLAGS = $(FAM_CFLAGS)
LEMON = $(top_builddir)/src/lemon
lemon_SOURCES = lemon.c
+lighttpd_angel_SOURCES = lighttpd-angel.c
common_src = buffer.c log.c \
keyvalue.c chunk.c \
http_chunk.c stream.c fdevent.c \
@@ -945,6 +951,9 @@ lemon$(EXEEXT): $(lemon_OBJECTS) $(lemon_DEPENDENCIES)
lighttpd$(EXEEXT): $(lighttpd_OBJECTS) $(lighttpd_DEPENDENCIES)
@rm -f lighttpd$(EXEEXT)
$(lighttpd_LINK) $(lighttpd_OBJECTS) $(lighttpd_LDADD) $(LIBS)
+lighttpd-angel$(EXEEXT): $(lighttpd_angel_OBJECTS) $(lighttpd_angel_DEPENDENCIES)
+ @rm -f lighttpd-angel$(EXEEXT)
+ $(LINK) $(lighttpd_angel_OBJECTS) $(lighttpd_angel_LDADD) $(LIBS)
proc_open$(EXEEXT): $(proc_open_OBJECTS) $(proc_open_DEPENDENCIES)
@rm -f proc_open$(EXEEXT)
$(LINK) $(proc_open_OBJECTS) $(proc_open_LDADD) $(LIBS)
@@ -1029,6 +1038,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-stat_cache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-status_counter.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblightcomp_la-stream.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lighttpd-angel.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_access.Plo@am__quote@
diff --git a/src/configparser.c b/src/configparser.c
index 292cff0..363b395 100644
--- a/src/configparser.c
+++ b/src/configparser.c
@@ -941,6 +941,7 @@ static void yy_reduce(
case 14:
#line 232 "./configparser.y"
{
+ yygotominor.yy41 = NULL;
if (strncmp(yymsp[0].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
char *env;
@@ -965,59 +966,59 @@ static void yy_reduce(
buffer_free(yymsp[0].minor.yy43);
yymsp[0].minor.yy43 = NULL;
}
-#line 968 "configparser.c"
+#line 969 "configparser.c"
break;
case 15:
-#line 258 "./configparser.y"
+#line 259 "./configparser.y"
{
yygotominor.yy41 = (data_unset *)data_string_init();
buffer_copy_string_buffer(((data_string *)(yygotominor.yy41))->value, yymsp[0].minor.yy0);
buffer_free(yymsp[0].minor.yy0);
yymsp[0].minor.yy0 = NULL;
}
-#line 978 "configparser.c"
+#line 979 "configparser.c"
break;
case 16:
-#line 265 "./configparser.y"
+#line 266 "./configparser.y"
{
yygotominor.yy41 = (data_unset *)data_integer_init();
((data_integer *)(yygotominor.yy41))->value = strtol(yymsp[0].minor.yy0->ptr, NULL, 10);
buffer_free(yymsp[0].minor.yy0);
yymsp[0].minor.yy0 = NULL;
}
-#line 988 "configparser.c"
+#line 989 "configparser.c"
break;
case 17:
-#line 271 "./configparser.y"
+#line 272 "./configparser.y"
{
yygotominor.yy41 = (data_unset *)data_array_init();
array_free(((data_array *)(yygotominor.yy41))->value);
((data_array *)(yygotominor.yy41))->value = yymsp[0].minor.yy40;
yymsp[0].minor.yy40 = NULL;
}
-#line 998 "configparser.c"
+#line 999 "configparser.c"
break;
case 18:
-#line 277 "./configparser.y"
+#line 278 "./configparser.y"
{
yygotominor.yy40 = array_init();
}
-#line 1005 "configparser.c"
+#line 1006 "configparser.c"
yy_destructor(8,&yymsp[-1].minor);
yy_destructor(9,&yymsp[0].minor);
break;
case 19:
-#line 280 "./configparser.y"
+#line 281 "./configparser.y"
{
yygotominor.yy40 = yymsp[-1].minor.yy40;
yymsp[-1].minor.yy40 = NULL;
}
-#line 1015 "configparser.c"
+#line 1016 "configparser.c"
yy_destructor(8,&yymsp[-2].minor);
yy_destructor(9,&yymsp[0].minor);
break;
case 20:
-#line 285 "./configparser.y"
+#line 286 "./configparser.y"
{
if (buffer_is_empty(yymsp[0].minor.yy41->key) ||
NULL == array_get_element(yymsp[-2].minor.yy40, yymsp[0].minor.yy41->key->ptr)) {
@@ -1034,37 +1035,37 @@ static void yy_reduce(
yygotominor.yy40 = yymsp[-2].minor.yy40;
yymsp[-2].minor.yy40 = NULL;
}
-#line 1037 "configparser.c"
+#line 1038 "configparser.c"
yy_destructor(10,&yymsp[-1].minor);
break;
case 21:
-#line 302 "./configparser.y"
+#line 303 "./configparser.y"
{
yygotominor.yy40 = yymsp[-1].minor.yy40;
yymsp[-1].minor.yy40 = NULL;
}
-#line 1046 "configparser.c"
+#line 1047 "configparser.c"
yy_destructor(10,&yymsp[0].minor);
break;
case 22:
-#line 307 "./configparser.y"
+#line 308 "./configparser.y"
{
yygotominor.yy40 = array_init();
array_insert_unique(yygotominor.yy40, yymsp[0].minor.yy41);
yymsp[0].minor.yy41 = NULL;
}
-#line 1056 "configparser.c"
+#line 1057 "configparser.c"
break;
case 23:
-#line 313 "./configparser.y"
+#line 314 "./configparser.y"
{
yygotominor.yy41 = yymsp[0].minor.yy41;
yymsp[0].minor.yy41 = NULL;
}
-#line 1064 "configparser.c"
+#line 1065 "configparser.c"
break;
case 24:
-#line 317 "./configparser.y"
+#line 318 "./configparser.y"
{
buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
buffer_free(yymsp[-2].minor.yy43);
@@ -1073,7 +1074,7 @@ static void yy_reduce(
yygotominor.yy41 = yymsp[0].minor.yy41;
yymsp[0].minor.yy41 = NULL;
}
-#line 1076 "configparser.c"
+#line 1077 "configparser.c"
yy_destructor(11,&yymsp[-1].minor);
break;
case 25:
@@ -1082,18 +1083,18 @@ static void yy_reduce(
case 26:
break;
case 27:
-#line 329 "./configparser.y"
+#line 330 "./configparser.y"
{
data_config *dc;
dc = (data_config *)array_get_element(ctx->srv->config_context, "global");
assert(dc);
configparser_push(ctx, dc, 0);
}
-#line 1092 "configparser.c"
+#line 1093 "configparser.c"
yy_destructor(12,&yymsp[0].minor);
break;
case 28:
-#line 336 "./configparser.y"
+#line 337 "./configparser.y"
{
data_config *cur;
@@ -1104,14 +1105,14 @@ static void yy_reduce(
yygotominor.yy0 = cur;
}
-#line 1107 "configparser.c"
+#line 1108 "configparser.c"
/* No destructor defined for globalstart */
yy_destructor(13,&yymsp[-2].minor);
/* No destructor defined for metalines */
yy_destructor(14,&yymsp[0].minor);
break;
case 29:
-#line 347 "./configparser.y"
+#line 348 "./configparser.y"
{
assert(yymsp[-3].minor.yy78->context_ndx < yymsp[0].minor.yy78->context_ndx);
yymsp[0].minor.yy78->prev = yymsp[-3].minor.yy78;
@@ -1120,20 +1121,20 @@ static void yy_reduce(
yymsp[-3].minor.yy78 = NULL;
yymsp[0].minor.yy78 = NULL;
}
-#line 1123 "configparser.c"
+#line 1124 "configparser.c"
/* No destructor defined for eols */
yy_destructor(15,&yymsp[-1].minor);
break;
case 30:
-#line 356 "./configparser.y"
+#line 357 "./configparser.y"
{
yygotominor.yy78 = yymsp[0].minor.yy78;
yymsp[0].minor.yy78 = NULL;
}
-#line 1133 "configparser.c"
+#line 1134 "configparser.c"
break;
case 31:
-#line 361 "./configparser.y"
+#line 362 "./configparser.y"
{
data_config *cur;
@@ -1144,14 +1145,14 @@ static void yy_reduce(
yygotominor.yy78 = cur;
}
-#line 1147 "configparser.c"
+#line 1148 "configparser.c"
/* No destructor defined for context */
yy_destructor(13,&yymsp[-2].minor);
/* No destructor defined for metalines */
yy_destructor(14,&yymsp[0].minor);
break;
case 32:
-#line 372 "./configparser.y"
+#line 373 "./configparser.y"
{
data_config *dc;
buffer *b, *rvalue, *op;
@@ -1287,45 +1288,45 @@ static void yy_reduce(
yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
yymsp[0].minor.yy41 = NULL;
}
-#line 1290 "configparser.c"
+#line 1291 "configparser.c"
yy_destructor(16,&yymsp[-6].minor);
yy_destructor(18,&yymsp[-4].minor);
yy_destructor(19,&yymsp[-2].minor);
break;
case 33:
-#line 507 "./configparser.y"
+#line 508 "./configparser.y"
{
yygotominor.yy27 = CONFIG_COND_EQ;
}
-#line 1300 "configparser.c"
+#line 1301 "configparser.c"
yy_destructor(20,&yymsp[0].minor);
break;
case 34:
-#line 510 "./configparser.y"
+#line 511 "./configparser.y"
{
yygotominor.yy27 = CONFIG_COND_MATCH;
}
-#line 1308 "configparser.c"
+#line 1309 "configparser.c"
yy_destructor(21,&yymsp[0].minor);
break;
case 35:
-#line 513 "./configparser.y"
+#line 514 "./configparser.y"
{
yygotominor.yy27 = CONFIG_COND_NE;
}
-#line 1316 "configparser.c"
+#line 1317 "configparser.c"
yy_destructor(22,&yymsp[0].minor);
break;
case 36:
-#line 516 "./configparser.y"
+#line 517 "./configparser.y"
{
yygotominor.yy27 = CONFIG_COND_NOMATCH;
}
-#line 1324 "configparser.c"
+#line 1325 "configparser.c"
yy_destructor(23,&yymsp[0].minor);
break;
case 37:
-#line 520 "./configparser.y"
+#line 521 "./configparser.y"
{
yygotominor.yy43 = NULL;
if (ctx->ok) {
@@ -1342,10 +1343,10 @@ static void yy_reduce(
yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
yymsp[0].minor.yy41 = NULL;
}
-#line 1345 "configparser.c"
+#line 1346 "configparser.c"
break;
case 38:
-#line 537 "./configparser.y"
+#line 538 "./configparser.y"
{
if (ctx->ok) {
if (0 != config_parse_file(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
@@ -1355,11 +1356,11 @@ static void yy_reduce(
yymsp[0].minor.yy43 = NULL;
}
}
-#line 1358 "configparser.c"
+#line 1359 "configparser.c"
yy_destructor(24,&yymsp[-1].minor);
break;
case 39:
-#line 547 "./configparser.y"
+#line 548 "./configparser.y"
{
if (ctx->ok) {
if (0 != config_parse_cmd(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
@@ -1369,7 +1370,7 @@ static void yy_reduce(
yymsp[0].minor.yy43 = NULL;
}
}
-#line 1372 "configparser.c"
+#line 1373 "configparser.c"
yy_destructor(25,&yymsp[-1].minor);
break;
};
@@ -1403,7 +1404,7 @@ static void yy_parse_failed(
ctx->ok = 0;
-#line 1406 "configparser.c"
+#line 1407 "configparser.c"
configparserARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
diff --git a/src/configparser.y b/src/configparser.y
index b5bc785..30f5fd9 100644
--- a/src/configparser.y
+++ b/src/configparser.y
@@ -230,6 +230,7 @@ expression(A) ::= value(B). {
}
value(A) ::= key(B). {
+ A = NULL;
if (strncmp(B->ptr, "env.", sizeof("env.") - 1) == 0) {
char *env;
diff --git a/src/connections.c b/src/connections.c
index 62b4d5e..94d36b4 100644
--- a/src/connections.c
+++ b/src/connections.c
@@ -537,7 +537,10 @@ static int connection_handle_write_prepare(server *srv, connection *con) {
con->http_status == 204 ||
con->http_status == 304) {
/* no Content-Body, no Content-Length */
- } else if (qlen > 0) {
+ } else if (qlen >= 0) {
+ /* qlen = 0 is important for Redirects (301, ...) as they MAY have
+ * a content. Browsers are waiting for a Content otherwise
+ */
buffer_copy_off_t(srv->tmp_buf, chunkqueue_length(con->write_queue));
response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));
diff --git a/src/http_auth.c b/src/http_auth.c
index b95b79b..1bfb460 100644
--- a/src/http_auth.c
+++ b/src/http_auth.c
@@ -831,19 +831,17 @@ int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p,
username = buffer_init();
if (!base64_decode(username, realm_str)) {
- buffer_free(username);
-
log_error_write(srv, __FILE__, __LINE__, "sb", "decodeing base64-string failed", username);
+ buffer_free(username);
return 0;
}
/* r2 == user:password */
if (NULL == (pw = strchr(username->ptr, ':'))) {
- buffer_free(username);
-
log_error_write(srv, __FILE__, __LINE__, "sb", ": is missing in", username);
+ buffer_free(username);
return 0;
}
diff --git a/src/lighttpd-angel.c b/src/lighttpd-angel.c
new file mode 100644
index 0000000..a6e3741
--- /dev/null
+++ b/src/lighttpd-angel.c
@@ -0,0 +1,154 @@
+/**
+ * angel process for lighttpd
+ *
+ * the purpose is the run as root all the time and handle:
+ * - restart on crash
+ * - spawn on HUP to allow graceful restart
+ * - ...
+ *
+ * it has to stay safe and small to be trustable
+ */
+
+#include <sys/wait.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <signal.h>
+
+#define BINPATH SBIN_DIR"/lighttpd"
+
+static siginfo_t last_sigterm_info;
+static siginfo_t last_sighup_info;
+
+static volatile sig_atomic_t start_process = 1;
+static volatile sig_atomic_t graceful_restart = 0;
+static volatile pid_t pid = -1;
+
+static void sigaction_handler(int sig, siginfo_t *si, void *context) {
+ int exitcode;
+
+ switch (sig) {
+ case SIGINT:
+ case SIGTERM:
+ memcpy(&last_sigterm_info, si, sizeof(*si));
+
+ /** forward the sig to the child */
+ kill(pid, sig);
+ break;
+ case SIGHUP: /** do a graceful restart */
+ memcpy(&last_sighup_info, si, sizeof(*si));
+
+ /** do a graceful shutdown on the main process and start a new child */
+ kill(pid, SIGINT);
+
+ usleep(5 * 1000); /** wait 5 microsec */
+
+ start_process = 1;
+ break;
+ case SIGCHLD:
+ /** a child died, de-combie it */
+ wait(&exitcode);
+ break;
+ }
+}
+
+int main(int argc, char **argv) {
+ int is_shutdown = 0;
+ struct sigaction act;
+
+ /**
+ * we are running as root BEWARE
+ */
+
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &act, NULL);
+ sigaction(SIGUSR1, &act, NULL);
+
+ act.sa_sigaction = sigaction_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+
+ sigaction(SIGINT, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
+ sigaction(SIGHUP, &act, NULL);
+ sigaction(SIGALRM, &act, NULL);
+ sigaction(SIGCHLD, &act, NULL);
+
+ /* check that the compiled in path has the right user,
+ *
+ * BEWARE: there is a race between the check here and the exec later
+ */
+
+ while (!is_shutdown) {
+ int exitcode = 0;
+
+ if (start_process) {
+ pid = fork();
+
+ if (0 == pid) {
+ /* i'm the child */
+
+ argv[0] = BINPATH;
+
+ execvp(BINPATH, argv);
+
+ exit(1);
+ } else if (-1 == pid) {
+ /** error */
+
+ return -1;
+ }
+
+ /* I'm the angel */
+ start_process = 0;
+ }
+
+ if ((pid_t)-1 == waitpid(pid, &exitcode, 0)) {
+ switch (errno) {
+ case EINTR:
+ /* someone sent a signal ...
+ * do we have to shutdown or restart the process */
+ break;
+ case ECHILD:
+ /**
+ * make sure we are not in a race between the signal handler
+ * and the process restart */
+ if (!start_process) is_shutdown = 1;
+ break;
+ default:
+ break;
+ }
+ } else {
+ /** process went away */
+
+ if (WIFEXITED(exitcode)) {
+ /** normal exit */
+
+ is_shutdown = 1;
+
+ fprintf(stderr, "%s.%d: child (pid=%d) exited normally with exitcode: %d\n",
+ __FILE__, __LINE__,
+ pid,
+ WEXITSTATUS(exitcode));
+
+ } else if (WIFSIGNALED(exitcode)) {
+ /** got a signal */
+
+ fprintf(stderr, "%s.%d: child (pid=%d) exited unexpectedly with signal %d, restarting\n",
+ __FILE__, __LINE__,
+ pid,
+ WTERMSIG(exitcode));
+
+ start_process = 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c
index e0dda30..75b52ad 100644
--- a/src/mod_fastcgi.c
+++ b/src/mod_fastcgi.c
@@ -49,6 +49,12 @@
#include <sys/wait.h>
#endif
+#define FCGI_ENV_ADD_CHECK(ret, con) \
+ if (ret == -1) { \
+ con->http_status = 400; \
+ con->file_finished = 1; \
+ return -1; \
+ };
/*
*
@@ -1571,6 +1577,21 @@ static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char
len += key_len > 127 ? 4 : 1;
len += val_len > 127 ? 4 : 1;
+ if (env->used + len >= FCGI_MAX_LENGTH) {
+ /**
+ * we can't append more headers, ignore it
+ */
+ return -1;
+ }
+
+ /**
+ * field length can be 31bit max
+ *
+ * HINT: this can't happen as FCGI_MAX_LENGTH is only 16bit
+ */
+ if (key_len > 0x7fffffff) key_len = 0x7fffffff;
+ if (val_len > 0x7fffffff) val_len = 0x7fffffff;
+
buffer_prepare_append(env, len);
if (key_len > 127) {
@@ -1600,6 +1621,8 @@ static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char
}
static int fcgi_header(FCGI_Header * header, unsigned char type, size_t request_id, int contentLength, unsigned char paddingLength) {
+ assert(contentLength <= FCGI_MAX_LENGTH);
+
header->version = FCGI_VERSION_1;
header->type = type;
header->requestIdB0 = request_id & 0xff;
@@ -1754,7 +1777,7 @@ static int fcgi_env_add_request_headers(server *srv, connection *con, plugin_dat
}
srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
- fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value)),con);
}
}
@@ -1781,7 +1804,7 @@ static int fcgi_env_add_request_headers(server *srv, connection *con, plugin_dat
}
srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
- fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value)), con);
}
}
@@ -1825,10 +1848,10 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) {
buffer_prepare_copy(p->fcgi_env, 1024);
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION)),con)
if (con->server_name->used) {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name)),con)
} else {
#ifdef HAVE_IPV6
s = inet_ntop(srv_sock->addr.plain.sa_family,
@@ -1839,10 +1862,10 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) {
#else
s = inet_ntoa(srv_sock->addr.ipv4.sin_addr);
#endif
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s)),con)
}
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1")),con)
LI_ltostr(buf,
#ifdef HAVE_IPV6
@@ -1852,7 +1875,7 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) {
#endif
);
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf)),con)
/* get the server-side of the connection to the client */
our_addr_len = sizeof(our_addr);
@@ -1862,7 +1885,7 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) {
} else {
s = inet_ntop_cache_get_ip(srv, &(our_addr));
}
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s)),con)
LI_ltostr(buf,
#ifdef HAVE_IPV6
@@ -1872,10 +1895,10 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) {
#endif
);
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf)),con)
s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s)),con)
if (!buffer_is_empty(con->authed_user)) {
/* AUTH_TYPE fix by Troy Kruthoff (tkruthoff@gmail.com)
@@ -1891,7 +1914,7 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) {
char *http_authorization = NULL;
data_string *ds;
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"), CONST_BUF_LEN(con->authed_user));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"), CONST_BUF_LEN(con->authed_user)),con)
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization"))) {
http_authorization = ds->value->ptr;
@@ -1915,7 +1938,7 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) {
/* request.content_length < SSIZE_MAX, see request.c */
LI_ltostr(buf, con->request.content_length);
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf)),con)
}
if (host->mode != FCGI_AUTHORIZER) {
@@ -1926,10 +1949,10 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) {
* For AUTHORIZER mode these headers should be omitted.
*/
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path)),con)
if (!buffer_is_empty(con->request.pathinfo)) {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo)),con)
/* PATH_TRANSLATED is only defined if PATH_INFO is set */
@@ -1939,9 +1962,9 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) {
buffer_copy_string_buffer(p->path, con->physical.doc_root);
}
buffer_append_string_buffer(p->path, con->request.pathinfo);
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_TRANSLATED"), CONST_BUF_LEN(p->path));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_TRANSLATED"), CONST_BUF_LEN(p->path)),con)
} else {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_STR_LEN(""));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_STR_LEN("")),con)
}
}
@@ -1962,8 +1985,8 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) {
buffer_copy_string_buffer(p->path, host->docroot);
buffer_append_string_buffer(p->path, con->uri.path);
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path)),con)
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot)),con)
} else {
buffer_copy_string_buffer(p->path, con->physical.path);
@@ -1975,8 +1998,8 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) {
buffer_append_string_buffer(p->path, con->request.pathinfo);
}
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path)),con)
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root)),con)
}
if (host->strip_request_uri->used > 1) {
@@ -2002,34 +2025,34 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) {
con->request.orig_uri->ptr + (host->strip_request_uri->used - 2),
con->request.orig_uri->used - (host->strip_request_uri->used - 2));
} else {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri)),con)
}
} else {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri)),con)
}
if (!buffer_is_equal(con->request.uri, con->request.orig_uri)) {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_URI"), CONST_BUF_LEN(con->request.uri));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_URI"), CONST_BUF_LEN(con->request.uri)),con)
}
if (!buffer_is_empty(con->uri.query)) {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query)),con)
} else {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN("")),con)
}
s = get_http_method_name(con->request.http_method);
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s)),con)
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")),con) /* if php is compiled with --force-redirect */
s = get_http_version_name(con->request.http_version);
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s)),con)
#ifdef USE_OPENSSL
if (srv_sock->is_ssl) {
- fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
+ FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on")),con)
}
#endif
- fcgi_env_add_request_headers(srv, con, p);
+ FCGI_ENV_ADD_CHECK(fcgi_env_add_request_headers(srv, con, p), con);
fcgi_header(&(header), FCGI_PARAMS, request_id, p->fcgi_env->used, 0);
buffer_append_memory(b, (const char *)&header, sizeof(header));
@@ -2924,10 +2947,8 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) {
}
/* fall through */
- fcgi_create_env(srv, hctx, hctx->request_id);
-
+ if (-1 == fcgi_create_env(srv, hctx, hctx->request_id)) return HANDLER_ERROR;
fcgi_set_state(srv, hctx, FCGI_STATE_WRITE);
-
/* fall through */
case FCGI_STATE_WRITE:
ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
@@ -3109,7 +3130,7 @@ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) {
buffer_reset(con->physical.path);
con->mode = DIRECT;
- con->http_status = 503;
+ if (con->http_status != 400) con->http_status = 503;
joblist_append(srv, con); /* really ? */
return HANDLER_FINISHED;
diff --git a/src/mod_mysql_vhost.c b/src/mod_mysql_vhost.c
index 65e7ce9..fe2b67f 100644
--- a/src/mod_mysql_vhost.c
+++ b/src/mod_mysql_vhost.c
@@ -222,7 +222,7 @@ SERVER_FUNC(mod_mysql_vhost_set_defaults) {
s->mysql_pre = buffer_init();
s->mysql_post = buffer_init();
- if (sel->used && (qmark = index(sel->ptr, '?'))) {
+ if (sel->used && (qmark = strchr(sel->ptr, '?'))) {
*qmark = '\0';
buffer_copy_string(s->mysql_pre, sel->ptr);
buffer_copy_string(s->mysql_post, qmark+1);
diff --git a/src/server.c b/src/server.c
index b610cdc..132eb32 100644
--- a/src/server.c
+++ b/src/server.c
@@ -68,6 +68,7 @@ static volatile sig_atomic_t srv_shutdown = 0;
static volatile sig_atomic_t graceful_shutdown = 0;
static volatile sig_atomic_t handle_sig_alarm = 1;
static volatile sig_atomic_t handle_sig_hup = 0;
+static volatile sig_atomic_t forwarded_sig_hup = 0;
#if defined(HAVE_SIGACTION) && defined(SA_SIGINFO)
static volatile siginfo_t last_sigterm_info;
@@ -94,8 +95,19 @@ static void sigaction_handler(int sig, siginfo_t *si, void *context) {
handle_sig_alarm = 1;
break;
case SIGHUP:
- handle_sig_hup = 1;
- memcpy(&last_sighup_info, si, sizeof(*si));
+ /**
+ * we send the SIGHUP to all procs in the process-group
+ * this includes ourself
+ *
+ * make sure we only send it once and don't create a
+ * infinite loop
+ */
+ if (!forwarded_sig_hup) {
+ handle_sig_hup = 1;
+ memcpy(&last_sighup_info, si, sizeof(*si));
+ } else {
+ forwarded_sig_hup = 0;
+ }
break;
case SIGCHLD:
break;
@@ -775,7 +787,10 @@ int main (int argc, char **argv) {
setuid(pwd->pw_uid);
}
#endif
-#ifdef HAVE_SYS_PRCTL_H
+#if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_DUMPABLE)
+ /**
+ * on IRIX 6.5.30 they have prctl() but no DUMPABLE
+ */
if (srv->srvconf.enable_cores) {
prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
}
@@ -985,7 +1000,7 @@ int main (int argc, char **argv) {
num_childs = srv->srvconf.max_worker;
if (num_childs > 0) {
int child = 0;
- while (!child && !srv_shutdown) {
+ while (!child && !srv_shutdown && !graceful_shutdown) {
if (num_childs > 0) {
switch (fork()) {
case -1:
@@ -1000,14 +1015,61 @@ int main (int argc, char **argv) {
} else {
int status;
- /* ignore EINTR */
- if (-1 != wait(&status)) num_childs++;
+ if (-1 != wait(&status)) {
+ /**
+ * one of our workers went away
+ */
+ num_childs++;
+ } else {
+ switch (errno) {
+ case EINTR:
+ /**
+ * if we receive a SIGHUP we have to close our logs ourself as we don't
+ * have the mainloop who can help us here
+ */
+ if (handle_sig_hup) {
+ handle_sig_hup = 0;
+
+ log_error_cycle(srv);
+
+ /**
+ * forward to all procs in the process-group
+ *
+ * we also send it ourself
+ */
+ if (!forwarded_sig_hup) {
+ forwarded_sig_hup = 1;
+ kill(0, SIGHUP);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
}
}
- if (srv_shutdown) {
- kill(0, SIGTERM);
+
+ /**
+ * for the parent this is the exit-point
+ */
+ if (!child) {
+ /**
+ * kill all children too
+ */
+ if (graceful_shutdown) {
+ kill(0, SIGINT);
+ } else if (srv_shutdown) {
+ kill(0, SIGTERM);
+ }
+
+ log_error_close(srv);
+ network_close(srv);
+ connections_free(srv);
+ plugins_free(srv);
+ server_free(srv);
+ return 0;
}
- if (!child) return 0;
}
#endif
@@ -1098,9 +1160,9 @@ int main (int argc, char **argv) {
#ifdef HAVE_SIGACTION
log_error_write(srv, __FILE__, __LINE__, "sdsd",
"logfiles cycled UID =",
- last_sigterm_info.si_uid,
+ last_sighup_info.si_uid,
"PID =",
- last_sigterm_info.si_pid);
+ last_sighup_info.si_pid);
#else
log_error_write(srv, __FILE__, __LINE__, "s",
"logfiles cycled");