Browse Source

uhttpd: block SIGCHLD until it is expected (#6957)

SVN-Revision: 20513
Jo-Philipp Wich 16 years ago
parent
commit
4172149f89

+ 1 - 1
package/uhttpd/Makefile

@@ -8,7 +8,7 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=uhttpd
-PKG_RELEASE:=3
+PKG_RELEASE:=4
 
 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
 

+ 1 - 1
package/uhttpd/src/uhttpd-cgi.c

@@ -376,7 +376,7 @@ void uh_cgi_request(struct client *cl, struct http_request *req, struct path_inf
 				FD_SET(wfd[1], &writer);
 
 				/* wait until we can read or write or both */
-				if( select(fd_max, &reader,
+				if( select_intr(fd_max, &reader,
 					(content_length > -1) ? &writer : NULL, NULL,
 					(header_sent < 1) ? &timeout : NULL) > 0
 				) {

+ 1 - 1
package/uhttpd/src/uhttpd-lua.c

@@ -452,7 +452,7 @@ void uh_lua_request(struct client *cl, struct http_request *req, lua_State *L)
 				FD_SET(wfd[1], &writer);
 
 				/* wait until we can read or write or both */
-				if( select(fd_max, &reader,
+				if( select_intr(fd_max, &reader,
 				    (content_length > -1) ? &writer : NULL, NULL,
 					(data_sent < 1) ? &timeout : NULL) > 0
 				) {

+ 19 - 0
package/uhttpd/src/uhttpd-utils.c

@@ -88,6 +88,25 @@ char *strfind(char *haystack, int hslen, const char *needle, int ndlen)
 	return NULL;
 }
 
+/* interruptable select() */
+int select_intr(int n, fd_set *r, fd_set *w, fd_set *e, struct timeval *t)
+{
+	int rv;
+	sigset_t ssn, sso;
+
+	/* unblock SIGCHLD */
+	sigemptyset(&ssn);
+	sigaddset(&ssn, SIGCHLD);
+	sigprocmask(SIG_UNBLOCK, &ssn, &sso);
+
+	rv = select(n, r, w, e, t);
+
+	/* restore signal mask */
+	sigprocmask(SIG_SETMASK, &sso, NULL);
+
+	return rv;
+}
+
 
 int uh_tcp_send(struct client *cl, const char *buf, int len)
 {

+ 2 - 0
package/uhttpd/src/uhttpd-utils.h

@@ -52,6 +52,8 @@ int sa_port(void *sa);
 
 char *strfind(char *haystack, int hslen, const char *needle, int ndlen);
 
+int select_intr(int n, fd_set *r, fd_set *w, fd_set *e, struct timeval *t);
+
 int uh_tcp_send(struct client *cl, const char *buf, int len);
 int uh_tcp_peek(struct client *cl, char *buf, int len);
 int uh_tcp_recv(struct client *cl, char *buf, int len);

+ 9 - 1
package/uhttpd/src/uhttpd.c

@@ -410,6 +410,9 @@ int main (int argc, char **argv)
 	struct sigaction sa;
 	struct config conf;
 
+	/* signal mask */
+	sigset_t ss;
+
 	/* maximum file descriptor number */
 	int new_fd, cur_fd, max_fd = 0;
 
@@ -432,7 +435,7 @@ int main (int argc, char **argv)
 	FD_ZERO(&serv_fds);
 	FD_ZERO(&read_fds);
 
-	/* handle SIGPIPE, SIGCHILD */
+	/* handle SIGPIPE, SIGINT, SIGTERM, SIGCHLD */
 	sa.sa_flags = 0;
 	sigemptyset(&sa.sa_mask);
 
@@ -446,6 +449,11 @@ int main (int argc, char **argv)
 	sigaction(SIGINT,  &sa, NULL);
 	sigaction(SIGTERM, &sa, NULL);
 
+	/* defer SIGCHLD */
+	sigemptyset(&ss);
+	sigaddset(&ss, SIGCHLD);
+	sigprocmask(SIG_BLOCK, &ss, NULL);
+
 	/* prepare addrinfo hints */
 	memset(&hints, 0, sizeof(hints));
 	hints.ai_family   = AF_UNSPEC;