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>
This commit is contained in:
parent
b5352078a7
commit
fbe250db76
@ -1105,16 +1105,21 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
|
|||||||
/* NB: breaking out of this loop jumps to log_and_exit() */
|
/* NB: breaking out of this loop jumps to log_and_exit() */
|
||||||
out_cnt = 0;
|
out_cnt = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
memset(pfd, 0, sizeof(pfd));
|
/* Note: even pfd[0].events == 0 won't prevent
|
||||||
|
* revents == POLLHUP|POLLERR reports from closed stdin.
|
||||||
|
* This works: */
|
||||||
|
pfd[0].fd = -1;
|
||||||
|
|
||||||
pfd[FROM_CGI].fd = fromCgi_rd;
|
pfd[FROM_CGI].fd = fromCgi_rd;
|
||||||
pfd[FROM_CGI].events = POLLIN;
|
pfd[FROM_CGI].events = POLLIN;
|
||||||
|
|
||||||
if (toCgi_wr) {
|
|
||||||
pfd[TO_CGI].fd = toCgi_wr;
|
pfd[TO_CGI].fd = toCgi_wr;
|
||||||
if (hdr_cnt > 0) {
|
|
||||||
pfd[TO_CGI].events = POLLOUT;
|
pfd[TO_CGI].events = POLLOUT;
|
||||||
} else if (post_len > 0) {
|
|
||||||
|
if (toCgi_wr && hdr_cnt <= 0) {
|
||||||
|
if (post_len > 0) {
|
||||||
|
/* Expect more POST data from network */
|
||||||
|
pfd[0].fd = 0;
|
||||||
pfd[0].events = POLLIN;
|
pfd[0].events = POLLIN;
|
||||||
} else {
|
} else {
|
||||||
/* post_len <= 0 && hdr_cnt <= 0:
|
/* 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
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Now wait on the set of sockets */
|
/* Now wait on the set of sockets */
|
||||||
count = safe_poll(pfd, toCgi_wr ? TO_CGI+1 : FROM_CGI+1, -1);
|
count = safe_poll(pfd, hdr_cnt > 0 ? TO_CGI+1 : FROM_CGI+1, -1);
|
||||||
if (count <= 0) {
|
if (count <= 0) {
|
||||||
#if 0
|
#if 0
|
||||||
if (safe_waitpid(pid, &status, WNOHANG) <= 0) {
|
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
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pfd[TO_CGI].revents) {
|
if (pfd[TO_CGI].revents) {
|
||||||
/* hdr_cnt > 0 here due to the way pfd[TO_CGI].events set */
|
/* hdr_cnt > 0 here due to the way poll() called */
|
||||||
/* Have data from peer and can write to CGI */
|
/* Have data from peer and can write to CGI */
|
||||||
count = safe_write(toCgi_wr, hdr_ptr, hdr_cnt);
|
count = safe_write(toCgi_wr, hdr_ptr, hdr_cnt);
|
||||||
/* Doesn't happen, we dont use nonblocking IO here
|
/* Doesn't happen, we dont use nonblocking IO here
|
||||||
|
Loading…
Reference in New Issue
Block a user