From c290767ed7ac0bd79004757529bbf4de0ff3d670 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 6 Sep 2010 11:11:40 +0000 Subject: [PATCH] Fixed bug #46723 (FastCGI persistent connection is incredibly slow due to TCP ack delay). --- sapi/cgi/fastcgi.c | 68 +++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/sapi/cgi/fastcgi.c b/sapi/cgi/fastcgi.c index 9d6ad82038..935f1ee80a 100644 --- a/sapi/cgi/fastcgi.c +++ b/sapi/cgi/fastcgi.c @@ -67,6 +67,7 @@ # include # include # include +# include # include # include # include @@ -337,12 +338,13 @@ static void fcgi_hash_apply(fcgi_hash *h, fcgi_apply_func func, void *arg TSRMLS struct _fcgi_request { int listen_socket; -#ifdef _WIN32 int tcp; -#endif int fd; int id; int keep; +#ifdef TCP_NODELAY + int nodelay; +#endif int closed; int in_len; @@ -746,6 +748,10 @@ fcgi_request *fcgi_init_request(int listen_socket) req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL); #endif +#ifdef TCP_NODELAY + req->nodelay = 0; +#endif + fcgi_hash_init(&req->env); return req; @@ -908,6 +914,18 @@ static int fcgi_read_request(fcgi_request *req) } req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN); +#ifdef TCP_NODELAY + if (req->keep && req->tcp && !req->nodelay) { +# ifdef _WIN32 + BOOL on = 1; +# else + int on = 1; +# endif + + setsockopt(req->fd, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on)); + req->nodelay = 1; + } +#endif switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) { case FCGI_RESPONDER: fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "RESPONDER", sizeof("RESPONDER")-1); @@ -1107,6 +1125,9 @@ static inline void fcgi_close(fcgi_request *req, int force, int destroy) recv(req->fd, &buf, sizeof(buf), 0); } close(req->fd); +#endif +#ifdef TCP_NODELAY + req->nodelay = 0; #endif req->fd = -1; } @@ -1158,24 +1179,33 @@ int fcgi_accept_request(fcgi_request *req) FCGI_LOCK(req->listen_socket); req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len); FCGI_UNLOCK(req->listen_socket); - if (req->fd >= 0 && - allowed_clients && - ((struct sockaddr *)&sa)->sa_family == AF_INET) { - int n = 0; - int allowed = 0; - - while (allowed_clients[n] != INADDR_NONE) { - if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) { - allowed = 1; - break; + if (req->fd >= 0) { + if (((struct sockaddr *)&sa)->sa_family == AF_INET) { +#ifndef _WIN32 + req->tcp = 1; +#endif + if (allowed_clients) { + int n = 0; + int allowed = 0; + + while (allowed_clients[n] != INADDR_NONE) { + if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) { + allowed = 1; + break; + } + n++; + } + if (!allowed) { + fprintf(stderr, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr)); + closesocket(req->fd); + req->fd = -1; + continue; + } } - n++; - } - if (!allowed) { - fprintf(stderr, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr)); - closesocket(req->fd); - req->fd = -1; - continue; +#ifndef _WIN32 + } else { + req->tcp = 0; +#endif } } } -- 2.40.0