fastcgi: Fix race condition when closing FastCGI connections
This commit is contained in:
+3
-2
@@ -407,10 +407,11 @@ int sock_has_pending(sock *s, int flags) {
|
|||||||
|
|
||||||
long sock_recv_chunk_header(sock *s) {
|
long sock_recv_chunk_header(sock *s) {
|
||||||
if (s->pipe) {
|
if (s->pipe) {
|
||||||
uint64_t len;
|
int64_t len;
|
||||||
if (sock_recv_x(s, &len, sizeof(len), 0) == -1)
|
if (sock_recv_x(s, &len, sizeof(len), 0) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
return (long) len;
|
if (len < 0) errno = ECONNABORTED;
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
long ret;
|
long ret;
|
||||||
|
|||||||
@@ -16,7 +16,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
void fastcgi_frame_handler_func(fastcgi_ctx_t *ctx) {
|
void fastcgi_frame_handler_func(fastcgi_ctx_t *ctx) {
|
||||||
logger_set_prefix("[%*s]%s", ADDRSTRLEN, ctx->client->socket.s_addr, ctx->client->log_prefix);
|
logger_set_prefix("%s", ctx->log_prefix);
|
||||||
|
int64_t val = 0;
|
||||||
|
|
||||||
switch (fastcgi_recv_frame(&ctx->cnx)) {
|
switch (fastcgi_recv_frame(&ctx->cnx)) {
|
||||||
case FCGI_STDOUT:
|
case FCGI_STDOUT:
|
||||||
@@ -25,12 +26,11 @@ void fastcgi_frame_handler_func(fastcgi_ctx_t *ctx) {
|
|||||||
break;
|
break;
|
||||||
case -1:
|
case -1:
|
||||||
error("Unable to receive FastCGI frame");
|
error("Unable to receive FastCGI frame");
|
||||||
ctx->client->s_keep_alive = 0;
|
val = -1;
|
||||||
fastcgi_close(ctx);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
// end of request received
|
// end of request received
|
||||||
write(ctx->cnx.fd_out, "\0\0\0\0\0\0\0\0\r\n", 10);
|
write(ctx->cnx.fd_out, &val, sizeof(val));
|
||||||
|
write(ctx->cnx.fd_out, "\r\n", 2);
|
||||||
fastcgi_close(ctx);
|
fastcgi_close(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,7 @@ int fastcgi_handle_connection(client_ctx_t *ctx, fastcgi_cnx_t **cnx) {
|
|||||||
|
|
||||||
fastcgi_ctx_t *a = malloc(sizeof(fastcgi_ctx_t));
|
fastcgi_ctx_t *a = malloc(sizeof(fastcgi_ctx_t));
|
||||||
a->closed = 0;
|
a->closed = 0;
|
||||||
a->client = ctx;
|
snprintf(a->log_prefix, sizeof(a->log_prefix), "[%*s]%s", ADDRSTRLEN, ctx->socket.s_addr, ctx->log_prefix);
|
||||||
memcpy(&a->cnx, *cnx, sizeof(fastcgi_cnx_t));
|
memcpy(&a->cnx, *cnx, sizeof(fastcgi_cnx_t));
|
||||||
ctx->fcgi_ctx = a;
|
ctx->fcgi_ctx = a;
|
||||||
fastcgi_handle_frame(a);
|
fastcgi_handle_frame(a);
|
||||||
@@ -55,7 +55,7 @@ void fastcgi_close(fastcgi_ctx_t *ctx) {
|
|||||||
if (ctx->closed != 2)
|
if (ctx->closed != 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
logger_set_prefix("[%*s]%s", ADDRSTRLEN, ctx->client->socket.s_addr, ctx->client->log_prefix);
|
logger_set_prefix("%s", ctx->log_prefix);
|
||||||
|
|
||||||
fastcgi_php_error(&ctx->cnx, NULL);
|
fastcgi_php_error(&ctx->cnx, NULL);
|
||||||
|
|
||||||
@@ -65,12 +65,11 @@ void fastcgi_close(fastcgi_ctx_t *ctx) {
|
|||||||
debug("Closing FastCGI connection");
|
debug("Closing FastCGI connection");
|
||||||
|
|
||||||
fastcgi_close_cnx(&ctx->cnx);
|
fastcgi_close_cnx(&ctx->cnx);
|
||||||
ctx->client->fcgi_ctx = NULL;
|
|
||||||
free(ctx);
|
free(ctx);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fastcgi_close_error(fastcgi_ctx_t *ctx) {
|
void fastcgi_close_error(fastcgi_ctx_t *ctx) {
|
||||||
logger_set_prefix("[%*s]%s", ADDRSTRLEN, ctx->client->socket.s_addr, ctx->client->log_prefix);
|
logger_set_prefix("%s", ctx->log_prefix);
|
||||||
fastcgi_close_cnx(&ctx->cnx);
|
fastcgi_close_cnx(&ctx->cnx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ void fastcgi_handler_func(client_ctx_t *ctx) {
|
|||||||
return;
|
return;
|
||||||
} else if (ctx->fcgi_ctx != NULL) {
|
} else if (ctx->fcgi_ctx != NULL) {
|
||||||
fastcgi_close(ctx->fcgi_ctx);
|
fastcgi_close(ctx->fcgi_ctx);
|
||||||
|
ctx->fcgi_ctx = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +45,6 @@ static int fastcgi_handler_1(client_ctx_t *ctx, fastcgi_cnx_t **fcgi_cnx) {
|
|||||||
http_uri *uri = &ctx->uri;
|
http_uri *uri = &ctx->uri;
|
||||||
sock *client = &ctx->socket;
|
sock *client = &ctx->socket;
|
||||||
char *err_msg = ctx->err_msg;
|
char *err_msg = ctx->err_msg;
|
||||||
char buf[1024];
|
|
||||||
|
|
||||||
int mode, ret;
|
int mode, ret;
|
||||||
if (strends(uri->filename, ".php")) {
|
if (strends(uri->filename, ".php")) {
|
||||||
@@ -131,7 +131,7 @@ static int fastcgi_handler_1(client_ctx_t *ctx, fastcgi_cnx_t **fcgi_cnx) {
|
|||||||
res->status = &ctx->custom_status;
|
res->status = &ctx->custom_status;
|
||||||
} else if (res->status == NULL) {
|
} else if (res->status == NULL) {
|
||||||
res->status = http_get_status(500);
|
res->status = http_get_status(500);
|
||||||
sprintf(err_msg, "The status_hdr code was set to an invalid or unknown value.");
|
sprintf(err_msg, "The status code was set to an invalid or unknown value.");
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,7 +177,6 @@ static void fastcgi_error_cb(chunk_ctx_t *ctx) {
|
|||||||
|
|
||||||
logger_set_prefix("[%s%*s%s]%s", BLD_STR, ADDRSTRLEN, ctx->client->req_host, CLR_STR, ctx->client->log_prefix);
|
logger_set_prefix("[%s%*s%s]%s", BLD_STR, ADDRSTRLEN, ctx->client->req_host, CLR_STR, ctx->client->log_prefix);
|
||||||
|
|
||||||
// FIXME segfault on error_cb
|
|
||||||
warning("Closing connection due to FastCGI error");
|
warning("Closing connection due to FastCGI error");
|
||||||
if(ctx->client->fcgi_ctx) {
|
if(ctx->client->fcgi_ctx) {
|
||||||
fastcgi_close_error(ctx->client->fcgi_ctx);
|
fastcgi_close_error(ctx->client->fcgi_ctx);
|
||||||
|
|||||||
+1
-1
@@ -47,7 +47,7 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned char closed:4;
|
unsigned char closed:4;
|
||||||
client_ctx_t *client;
|
char log_prefix[128];
|
||||||
fastcgi_cnx_t cnx;
|
fastcgi_cnx_t cnx;
|
||||||
} fastcgi_ctx_t;
|
} fastcgi_ctx_t;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user