aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2013-09-11 14:59:21 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2013-09-11 14:59:21 +0200
commitfbe250db76b409a99457b47486a09b57677d5108 (patch)
tree1b222f195c0947502c46d375e35f549eb4cbe9b0
parentb5352078a7eb16c33404a8b079aaa9c2b994546c (diff)
downloadbusybox-w32-fbe250db76b409a99457b47486a09b57677d5108.tar.gz
busybox-w32-fbe250db76b409a99457b47486a09b57677d5108.tar.bz2
busybox-w32-fbe250db76b409a99457b47486a09b57677d5108.zip
httpd: treat errors from stdin correctly.
Fron bug report: If a CGI or proxied connection is rudely aborted (SIG_{KILL,BUS,SEGV}) then httpd will spin madly the poll loop in: networking/httpd.c:1080 cgi_io_loop_and_exit() Upon investigation I found that pfd[0].revents == 0x0018 (POLLHUP|POLLERR), which leads to empty read, but the pfd[0].fd (STDIN_FILENO) is left open, and in the FD list given to poll() which immediately returns to once again inform the loop of (POLLHUP|POLLERR) condition of pfd[0].fd. This continues until pfd[FROM_CGI].revents != 0 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/httpd.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/networking/httpd.c b/networking/httpd.c
index cef9b8baf..143331389 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -1105,16 +1105,21 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
1105 /* NB: breaking out of this loop jumps to log_and_exit() */ 1105 /* NB: breaking out of this loop jumps to log_and_exit() */
1106 out_cnt = 0; 1106 out_cnt = 0;
1107 while (1) { 1107 while (1) {
1108 memset(pfd, 0, sizeof(pfd)); 1108 /* Note: even pfd[0].events == 0 won't prevent
1109 * revents == POLLHUP|POLLERR reports from closed stdin.
1110 * This works: */
1111 pfd[0].fd = -1;
1109 1112
1110 pfd[FROM_CGI].fd = fromCgi_rd; 1113 pfd[FROM_CGI].fd = fromCgi_rd;
1111 pfd[FROM_CGI].events = POLLIN; 1114 pfd[FROM_CGI].events = POLLIN;
1112 1115
1113 if (toCgi_wr) { 1116 pfd[TO_CGI].fd = toCgi_wr;
1114 pfd[TO_CGI].fd = toCgi_wr; 1117 pfd[TO_CGI].events = POLLOUT;
1115 if (hdr_cnt > 0) { 1118
1116 pfd[TO_CGI].events = POLLOUT; 1119 if (toCgi_wr && hdr_cnt <= 0) {
1117 } else if (post_len > 0) { 1120 if (post_len > 0) {
1121 /* Expect more POST data from network */
1122 pfd[0].fd = 0;
1118 pfd[0].events = POLLIN; 1123 pfd[0].events = POLLIN;
1119 } else { 1124 } else {
1120 /* post_len <= 0 && hdr_cnt <= 0: 1125 /* post_len <= 0 && hdr_cnt <= 0:
@@ -1127,7 +1132,7 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
1127 } 1132 }
1128 1133
1129 /* Now wait on the set of sockets */ 1134 /* Now wait on the set of sockets */
1130 count = safe_poll(pfd, toCgi_wr ? TO_CGI+1 : FROM_CGI+1, -1); 1135 count = safe_poll(pfd, hdr_cnt > 0 ? TO_CGI+1 : FROM_CGI+1, -1);
1131 if (count <= 0) { 1136 if (count <= 0) {
1132#if 0 1137#if 0
1133 if (safe_waitpid(pid, &status, WNOHANG) <= 0) { 1138 if (safe_waitpid(pid, &status, WNOHANG) <= 0) {
@@ -1144,7 +1149,7 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
1144 } 1149 }
1145 1150
1146 if (pfd[TO_CGI].revents) { 1151 if (pfd[TO_CGI].revents) {
1147 /* hdr_cnt > 0 here due to the way pfd[TO_CGI].events set */ 1152 /* hdr_cnt > 0 here due to the way poll() called */
1148 /* Have data from peer and can write to CGI */ 1153 /* Have data from peer and can write to CGI */
1149 count = safe_write(toCgi_wr, hdr_ptr, hdr_cnt); 1154 count = safe_write(toCgi_wr, hdr_ptr, hdr_cnt);
1150 /* Doesn't happen, we dont use nonblocking IO here 1155 /* Doesn't happen, we dont use nonblocking IO here