Lines 444-450
Link Here
|
444 |
apr_uint16_t request_id, const char **err, |
444 |
apr_uint16_t request_id, const char **err, |
445 |
int *bad_request, int *has_responded) |
445 |
int *bad_request, int *has_responded) |
446 |
{ |
446 |
{ |
447 |
apr_bucket_brigade *ib, *ob; |
447 |
apr_bucket_brigade *ib, *ob, *cib; |
448 |
int seen_end_of_headers = 0, done = 0, ignore_body = 0; |
448 |
int seen_end_of_headers = 0, done = 0, ignore_body = 0; |
449 |
apr_status_t rv = APR_SUCCESS; |
449 |
apr_status_t rv = APR_SUCCESS; |
450 |
int script_error_status = HTTP_OK; |
450 |
int script_error_status = HTTP_OK; |
Lines 452-458
Link Here
|
452 |
struct iovec vec[2]; |
452 |
struct iovec vec[2]; |
453 |
ap_fcgi_header header; |
453 |
ap_fcgi_header header; |
454 |
unsigned char farray[AP_FCGI_HEADER_LEN]; |
454 |
unsigned char farray[AP_FCGI_HEADER_LEN]; |
455 |
apr_pollfd_t pfd; |
455 |
apr_pollfd_t pfd[2]; |
456 |
int header_state = HDR_STATE_READING_HEADERS; |
456 |
int header_state = HDR_STATE_READING_HEADERS; |
457 |
char stack_iobuf[AP_IOBUFSIZE]; |
457 |
char stack_iobuf[AP_IOBUFSIZE]; |
458 |
apr_size_t iobuf_size = AP_IOBUFSIZE; |
458 |
apr_size_t iobuf_size = AP_IOBUFSIZE; |
Lines 464-476
Link Here
|
464 |
iobuf = apr_palloc(r->pool, iobuf_size); |
464 |
iobuf = apr_palloc(r->pool, iobuf_size); |
465 |
} |
465 |
} |
466 |
pfd.desc_type = APR_POLL_SOCKET; |
466 |
pfd[0].desc_type = APR_POLL_SOCKET; |
467 |
pfd.desc.s = conn->sock; |
467 |
pfd[0].desc.s = conn->sock; |
468 |
pfd.p = r->pool; |
468 |
pfd[0].p = r->pool; |
469 |
pfd.reqevents = APR_POLLIN | APR_POLLOUT; |
469 |
pfd[0].reqevents = APR_POLLIN | APR_POLLOUT; |
|
|
470 |
/* Specific pollfd to detect client connection aborts */ |
471 |
pfd[1].desc_type = APR_POLL_SOCKET; |
472 |
pfd[1].desc.s = (apr_socket_t*) ap_get_module_config(r->connection->conn_config, |
473 |
&core_module); |
474 |
pfd[1].p = r->connection->pool; |
475 |
pfd[1].reqevents = APR_POLLIN; |
476 |
|
470 |
ib = apr_brigade_create(r->pool, c->bucket_alloc); |
477 |
ib = apr_brigade_create(r->pool, c->bucket_alloc); |
471 |
ob = apr_brigade_create(r->pool, c->bucket_alloc); |
478 |
ob = apr_brigade_create(r->pool, c->bucket_alloc); |
|
|
479 |
cib = apr_brigade_create(r->connection->pool, c->bucket_alloc); |
472 |
while (! done) { |
480 |
while (! done) { |
473 |
apr_interval_time_t timeout; |
481 |
apr_interval_time_t timeout; |
Lines 481-487
Link Here
|
481 |
* cause timeout errors. */ |
489 |
* cause timeout errors. */ |
482 |
apr_socket_timeout_get(conn->sock, &timeout); |
490 |
apr_socket_timeout_get(conn->sock, &timeout); |
483 |
rv = apr_poll(&pfd, 1, &n, timeout); |
491 |
rv = apr_poll(pfd, 2, &n, timeout); |
484 |
if (rv != APR_SUCCESS) { |
492 |
if (rv != APR_SUCCESS) { |
485 |
if (APR_STATUS_IS_EINTR(rv)) { |
493 |
if (APR_STATUS_IS_EINTR(rv)) { |
486 |
continue; |
494 |
continue; |
Lines 490-496
Link Here
|
490 |
break; |
498 |
break; |
491 |
} |
499 |
} |
492 |
if (pfd.rtnevents & APR_POLLOUT) { |
500 |
if (pfd[0].rtnevents & APR_POLLOUT) { |
493 |
apr_size_t to_send, writebuflen; |
501 |
apr_size_t to_send, writebuflen; |
494 |
int last_stdin = 0; |
502 |
int last_stdin = 0; |
495 |
char *iobuf_cursor; |
503 |
char *iobuf_cursor; |
Lines 555-561
Link Here
|
555 |
} |
563 |
} |
556 |
if (last_stdin) { |
564 |
if (last_stdin) { |
557 |
pfd.reqevents = APR_POLLIN; /* Done with input data */ |
565 |
pfd[0].reqevents = APR_POLLIN; /* Done with input data */ |
558 |
/* signal EOF (empty FCGI_STDIN) */ |
566 |
/* signal EOF (empty FCGI_STDIN) */ |
559 |
ap_fcgi_fill_in_header(&header, AP_FCGI_STDIN, request_id, |
567 |
ap_fcgi_fill_in_header(&header, AP_FCGI_STDIN, request_id, |
Lines 573-579
Link Here
|
573 |
} |
581 |
} |
574 |
} |
582 |
} |
575 |
if (pfd.rtnevents & APR_POLLIN) { |
583 |
/* |
|
|
584 |
* Client connection aborted before any attempt to flush |
585 |
* data out has been made. This can happen for long running FCGI |
586 |
* tasks. According to the FCGI specs, in the general case FCGI_ABORT |
587 |
* should be sent to the FCGI backend, that it turns should inform the |
588 |
* running application and finally respond with the appropriate |
589 |
* END_REQUEST containing the final status of the (interrupted) |
590 |
* FCGI response. As the specs dictates, this should be a response from |
591 |
* the application, not a low-level acknowledgement from |
592 |
* the FastCGI library. |
593 |
* When a Web server is not multiplexing requests over a transport |
594 |
* connection (this module does not support it), it can abort a request |
595 |
* by simply closing the request's transport connection. |
596 |
* As of today (January 2017) there seems to be no FCGI backend |
597 |
* implementation that really honors/cares about FCGI_ABORT in the way |
598 |
* described by the specs, so it has not been implemented. |
599 |
*/ |
600 |
if (pfd[1].rtnevents & APR_POLLIN) { |
601 |
rv = ap_get_brigade(r->connection->input_filters, cib, |
602 |
AP_MODE_SPECULATIVE, APR_NONBLOCK_READ, 8); |
603 |
if(rv == APR_EOF) { |
604 |
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, |
605 |
"EOF detected from the main client connection."); |
606 |
r->connection->aborted = 1; |
607 |
break; |
608 |
} |
609 |
} |
610 |
|
611 |
if (pfd[0].rtnevents & APR_POLLIN) { |
576 |
apr_size_t readbuflen; |
612 |
apr_size_t readbuflen; |
577 |
apr_uint16_t clen, rid; |
613 |
apr_uint16_t clen, rid; |
578 |
apr_bucket *b; |
614 |
apr_bucket *b; |
Lines 802-807
Link Here
|
802 |
apr_brigade_destroy(ib); |
838 |
apr_brigade_destroy(ib); |
803 |
apr_brigade_destroy(ob); |
839 |
apr_brigade_destroy(ob); |
|
|
840 |
apr_brigade_destroy(cib); |
804 |
if (script_error_status != HTTP_OK) { |
841 |
if (script_error_status != HTTP_OK) { |
805 |
ap_die(script_error_status, r); /* send ErrorDocument */ |
842 |
ap_die(script_error_status, r); /* send ErrorDocument */ |