From: Bill Stoddard Date: Thu, 11 Jan 2001 18:50:09 +0000 (+0000) Subject: It is not sufficient to reset the file pointer before each call to ap_send_fd. A... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0e4084c6c2a768a54507ffb68d34a93da2504d26;p=apache It is not sufficient to reset the file pointer before each call to ap_send_fd. A better solution is to make certain that only apr_sendfile() will be used to send content with a cached file handle. This assumes that apr_sendfile() should not rely on the position of the file pointer. I suspect that sendfile implementations that rely on the position of the file pointer are broken and we should not use sendfile on those platforms. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@87654 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/cache/mod_file_cache.c b/modules/cache/mod_file_cache.c index 261dd29802..cf03c109ee 100644 --- a/modules/cache/mod_file_cache.c +++ b/modules/cache/mod_file_cache.c @@ -216,6 +216,12 @@ static apr_status_t cleanup_file_cache(void *sconfv) static const char *cachefile(cmd_parms *cmd, void *dummy, const char *filename) { + /* ToDo: + * Disable the file cache on a Windows 9X box. APR_HAS_SENDFILE will be + * defined in an Apache for Windows build, but apr_sendfile is not + * implemened on Windows 9X because TransmitFile is not available. + */ + #if APR_HAS_SENDFILE a_server_config *sconf; a_file *new_file; @@ -400,13 +406,28 @@ static int sendfile_handler(request_rec *r, a_file *file) apr_status_t rv = APR_EINIT; apr_off_t offset = 0; - rv = apr_seek(file->file, APR_SET, &offset); - if (rv != APR_SUCCESS) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, - "seek failed"); - return HTTP_INTERNAL_SERVER_ERROR; + /* A cached file handle (more importantly, its file pointer) is + * shared by all threads in the process. The file pointer will + * be corrupted if multiple threads attempt to read from the + * cached file handle. The sendfile API does not rely on the position + * of the file pointer instead taking explicit file offset and + * length arguments. + * + * We should call ap_send_fd with a cached file handle IFF + * we are CERTAIN the file will be served with apr_sendfile(). + * The presense of an AP_FTYPE_FILTER in the filter chain nearly + * guarantees that apr_sendfile will NOT be used to send the file. + * Furthermore, AP_FTYPE_CONTENT filters will be at the beginning + * of the chain, so it should suffice to just check the first + * filter in the chain. If the first filter is not a content filter, + * assume apr_sendfile() will be used to send the content. + */ + if (r->output_filters && r->output_filters->frec) { + if (r->output_filters->frec->ftype == AP_FTYPE_CONTENT) + return DECLINED; } + rv = ap_send_fd(file->file, r, 0, file->finfo.size, &nbytes); if (rv != APR_SUCCESS) { /* ap_send_fd will log the error */