View | Details | Raw Unified | Return to bug 56188
Collapse All | Expand All

(-)modules/proxy/mod_proxy_fcgi.c (-12 / +91 lines)
Lines 40-45 Link Here
40
    fcgi_backend_t backend_type;
40
    fcgi_backend_t backend_type;
41
} fcgi_dirconf_t;
41
} fcgi_dirconf_t;
42
typedef struct {
43
    int detect_client_disconnect;
44
} fcgi_serverconf_t;
45
42
/*
46
/*
43
 * Canonicalise http-like URLs.
47
 * Canonicalise http-like URLs.
44
 * scheme is the scheme for the URL
48
 * scheme is the scheme for the URL
Lines 497-503 Link Here
497
                             apr_uint16_t request_id, const char **err,
501
                             apr_uint16_t request_id, const char **err,
498
                             int *bad_request, int *has_responded)
502
                             int *bad_request, int *has_responded)
499
{
503
{
500
    apr_bucket_brigade *ib, *ob;
504
    apr_bucket_brigade *ib, *ob, *cib;
501
    int seen_end_of_headers = 0, done = 0, ignore_body = 0;
505
    int seen_end_of_headers = 0, done = 0, ignore_body = 0;
502
    apr_status_t rv = APR_SUCCESS;
506
    apr_status_t rv = APR_SUCCESS;
503
    int script_error_status = HTTP_OK;
507
    int script_error_status = HTTP_OK;
Lines 505-511 Link Here
505
    struct iovec vec[2];
509
    struct iovec vec[2];
506
    ap_fcgi_header header;
510
    ap_fcgi_header header;
507
    unsigned char farray[AP_FCGI_HEADER_LEN];
511
    unsigned char farray[AP_FCGI_HEADER_LEN];
508
    apr_pollfd_t pfd;
512
    apr_pollfd_t pfd[2];
509
    int header_state = HDR_STATE_READING_HEADERS;
513
    int header_state = HDR_STATE_READING_HEADERS;
510
    char stack_iobuf[AP_IOBUFSIZE];
514
    char stack_iobuf[AP_IOBUFSIZE];
511
    apr_size_t iobuf_size = AP_IOBUFSIZE;
515
    apr_size_t iobuf_size = AP_IOBUFSIZE;
Lines 517-530 Link Here
517
        iobuf = apr_palloc(r->pool, iobuf_size);
521
        iobuf = apr_palloc(r->pool, iobuf_size);
518
    }
522
    }
519
    pfd.desc_type = APR_POLL_SOCKET;
523
    pfd[0].desc_type = APR_POLL_SOCKET;
520
    pfd.desc.s = conn->sock;
524
    pfd[0].desc.s = conn->sock;
521
    pfd.p = r->pool;
525
    pfd[0].p = r->pool;
522
    pfd.reqevents = APR_POLLIN | APR_POLLOUT;
526
    pfd[0].reqevents = APR_POLLIN | APR_POLLOUT;
527
    /* Specific pollfd to detect client connection aborts */
528
    pfd[1].desc_type = APR_POLL_SOCKET;
529
    pfd[1].desc.s = (apr_socket_t*) ap_get_module_config(r->connection->conn_config,
530
                                                         &core_module);
531
    pfd[1].p = r->connection->pool;
532
    pfd[1].reqevents = APR_POLLIN;
533
523
    ib = apr_brigade_create(r->pool, c->bucket_alloc);
534
    ib = apr_brigade_create(r->pool, c->bucket_alloc);
524
    ob = apr_brigade_create(r->pool, c->bucket_alloc);
535
    ob = apr_brigade_create(r->pool, c->bucket_alloc);
536
    cib = apr_brigade_create(r->connection->pool, c->bucket_alloc);
537
    fcgi_serverconf_t *cfg = ap_get_module_config(r->server->module_config,
538
                                                  &proxy_fcgi_module);
539
525
    while (! done) {
540
    while (! done) {
526
        apr_interval_time_t timeout;
541
        apr_interval_time_t timeout;
527
        apr_size_t len;
542
        apr_size_t len;
Lines 534-540 Link Here
534
         * cause timeout errors. */
549
         * cause timeout errors. */
535
        apr_socket_timeout_get(conn->sock, &timeout);
550
        apr_socket_timeout_get(conn->sock, &timeout);
536
        rv = apr_poll(&pfd, 1, &n, timeout);
551
        rv = apr_poll(pfd, 2, &n, timeout);
537
        if (rv != APR_SUCCESS) {
552
        if (rv != APR_SUCCESS) {
538
            if (APR_STATUS_IS_EINTR(rv)) {
553
            if (APR_STATUS_IS_EINTR(rv)) {
539
                continue;
554
                continue;
Lines 543-549 Link Here
543
            break;
558
            break;
544
        }
559
        }
545
        if (pfd.rtnevents & APR_POLLOUT) {
560
        if (pfd[0].rtnevents & APR_POLLOUT) {
546
            apr_size_t to_send, writebuflen;
561
            apr_size_t to_send, writebuflen;
547
            int last_stdin = 0;
562
            int last_stdin = 0;
548
            char *iobuf_cursor;
563
            char *iobuf_cursor;
Lines 608-614 Link Here
608
            }
623
            }
609
            if (last_stdin) {
624
            if (last_stdin) {
610
                pfd.reqevents = APR_POLLIN; /* Done with input data */
625
                pfd[0].reqevents = APR_POLLIN; /* Done with input data */
611
                /* signal EOF (empty FCGI_STDIN) */
626
                /* signal EOF (empty FCGI_STDIN) */
612
                ap_fcgi_fill_in_header(&header, AP_FCGI_STDIN, request_id,
627
                ap_fcgi_fill_in_header(&header, AP_FCGI_STDIN, request_id,
Lines 626-632 Link Here
626
            }
641
            }
627
        }
642
        }
628
        if (pfd.rtnevents & APR_POLLIN) {
643
        /*
644
         * Client connection aborted before any attempt to flush
645
         * data out has been made. This can happen for long running FCGI
646
         * tasks. According to the FCGI specs, an FCGI_ABORT should be sent
647
         * and the FCGI backend should respond with an FCGI_END_REQUEST, but as of
648
         * today (December 2016) there seems to be no FCGI backend implementation
649
         * that really honor/care about this functionality. Since this module
650
         * does not implement FCGI request multiplexing, it seems more consistent
651
         * to follow this bit of the FCGI_ABORT spec:
652
         * "When a Web server is not multiplexing requests over a transport
653
         * connection, the Web server can abort a request by closing
654
         * the request's transport connection."
655
         */
656
        if (pfd[1].rtnevents & APR_POLLIN) {
657
            if (cfg->detect_client_disconnect) {
658
                rv = ap_get_brigade(r->connection->input_filters, cib,
659
                                    AP_MODE_SPECULATIVE, APR_NONBLOCK_READ, 8);
660
                if(rv == APR_EOF) {
661
                    ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
662
                                  "EOF detected from the main client connection.");
663
                    r->connection->aborted = 1;
664
                    break;
665
                }
666
            } else {
667
                ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
668
                              "Client disconnect detector disabled!");
669
            }
670
        }
671
672
        if (pfd[0].rtnevents & APR_POLLIN) {
629
            apr_size_t readbuflen;
673
            apr_size_t readbuflen;
630
            apr_uint16_t clen, rid;
674
            apr_uint16_t clen, rid;
631
            apr_bucket *b;
675
            apr_bucket *b;
Lines 855-860 Link Here
855
    apr_brigade_destroy(ib);
899
    apr_brigade_destroy(ib);
856
    apr_brigade_destroy(ob);
900
    apr_brigade_destroy(ob);
901
    apr_brigade_destroy(cib);
857
    if (script_error_status != HTTP_OK) {
902
    if (script_error_status != HTTP_OK) {
858
        ap_die(script_error_status, r); /* send ErrorDocument */
903
        ap_die(script_error_status, r); /* send ErrorDocument */
Lines 1052-1057 Link Here
1052
    return a;
1097
    return a;
1053
}
1098
}
1099
static void *fcgi_create_sconf(apr_pool_t *p, server_rec *s)
1100
{
1101
    fcgi_serverconf_t *a;
1102
1103
    a = (fcgi_serverconf_t *) apr_pcalloc(p, sizeof(fcgi_serverconf_t));
1104
    a->detect_client_disconnect = 0;
1105
    return a;
1106
}
1107
1108
static void *fcgi_merge_sconf(apr_pool_t *p, void *basev, void *overridesv)
1109
{
1110
    fcgi_serverconf_t *a, *override;
1111
1112
    override = (fcgi_serverconf_t *) overridesv;
1113
    a = (fcgi_serverconf_t *) apr_pcalloc(p, sizeof(fcgi_serverconf_t));
1114
    a->detect_client_disconnect = override->detect_client_disconnect;
1115
    return a;
1116
}
1117
1054
static const char *cmd_servertype(cmd_parms *cmd, void *in_dconf,
1118
static const char *cmd_servertype(cmd_parms *cmd, void *in_dconf,
1055
                                   const char *val)
1119
                                   const char *val)
1056
{
1120
{
Lines 1071-1076 Link Here
1071
    return NULL;
1135
    return NULL;
1072
}
1136
}
1137
const char *cmd_client_disconnect(cmd_parms *cmd, void *cfg, const char *arg)
1138
{
1139
    fcgi_serverconf_t *config = ap_get_module_config(cmd->server->module_config,
1140
                                                     &proxy_fcgi_module);
1141
    if(!strcasecmp(arg, "on")) {
1142
        config->detect_client_disconnect = 1;
1143
    } else {
1144
        config->detect_client_disconnect = 0;
1145
    }
1146
    return NULL;
1147
}
1148
1073
static void register_hooks(apr_pool_t *p)
1149
static void register_hooks(apr_pool_t *p)
1074
{
1150
{
1075
    proxy_hook_scheme_handler(proxy_fcgi_handler, NULL, NULL, APR_HOOK_FIRST);
1151
    proxy_hook_scheme_handler(proxy_fcgi_handler, NULL, NULL, APR_HOOK_FIRST);
Lines 1080-1085 Link Here
1080
static const command_rec command_table[] = {
1156
static const command_rec command_table[] = {
1081
    AP_INIT_TAKE1("ProxyFCGIBackendType", cmd_servertype, NULL, OR_FILEINFO,
1157
    AP_INIT_TAKE1("ProxyFCGIBackendType", cmd_servertype, NULL, OR_FILEINFO,
1082
                  "Specify the type of FastCGI server: 'Generic', 'FPM'"),
1158
                  "Specify the type of FastCGI server: 'Generic', 'FPM'"),
1159
    AP_INIT_TAKE1("ProxyFCGIDetectClientDisconnect", cmd_client_disconnect,
1160
                  NULL, RSRC_CONF, "Detect when a client connection is dropped"
1161
                  " and close the connection with the FCGI backend."),
1083
    { NULL }
1162
    { NULL }
1084
};
1163
};
Lines 1087-1094 Link Here
1087
    STANDARD20_MODULE_STUFF,
1166
    STANDARD20_MODULE_STUFF,
1088
    fcgi_create_dconf,          /* create per-directory config structure */
1167
    fcgi_create_dconf,          /* create per-directory config structure */
1089
    fcgi_merge_dconf,           /* merge per-directory config structures */
1168
    fcgi_merge_dconf,           /* merge per-directory config structures */
1090
    NULL,                       /* create per-server config structure */
1169
    fcgi_create_sconf,          /* create per-server config structure */
1091
    NULL,                       /* merge per-server config structures */
1170
    fcgi_merge_sconf,           /* merge per-server config structures */
1092
    command_table,              /* command apr_table_t */
1171
    command_table,              /* command apr_table_t */
1093
    register_hooks              /* register hooks */
1172
    register_hooks              /* register hooks */
1094
};
1173
};

Return to bug 56188