Commits

Anonymous committed 826d472

Ensure the FastCGI process always receives a blocking socket

From version 0.2.3, the socket egg immediately places the sockets it
creates into non-blocking mode. In previous versions it only used to do
this during socket-connect and socket-accept. As these procedures were
never called on the socket we create for the FastCGI process we always has
a regular blocking socket in hand.

The FCGX_Accept_r() call expects a blocking socket. If the socket does not
block then FCGX_Accept_r() returns a non-zero value and the FastCGI process
exits.

Here we ensure that the socket is in blocking mode after we fork but before
we exec the FastCGI binary. This means that the child process gets the
blocking socket that it expects but the socket in the CHICKEN parent is as
the socket egg created it.

Signed-off-by: Andy Bennett <andyjpb@knodium.com>

Comments (0)

Files changed (1)

 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <fcntl.h>
 #include "fastcgi.h"
 #include "fork-exec.h"
 
 	switch ((child = fork())) {
 		case 0: { /* Child */
 				size_t i = 0;
+				int val = 0;
+
+				/* Ensure the socket is in blocking mode. */
+#ifdef _WIN32
+#error We don't have code to set the socket to blocking mode for Windows.
+#else
+				errno = 0;
+				val = fcntl(fcgi_fd, F_GETFL, 0);
+				if (val == -1) {
+					perror("fcntl F_GETFL");
+					exit(errno);
+				}
+				errno = 0;
+				val = fcntl(fcgi_fd, F_SETFL, val & ~O_NONBLOCK);
+				if (val == -1) {
+					perror("fcntl F_SETFL");
+					exit(errno);
+				}
+#endif
 
 				if (fcgi_fd != FCGI_LISTENSOCK_FILENO) {
 					close(FCGI_LISTENSOCK_FILENO);