mirror of
https://github.com/cesanta/mongoose.git
synced 2025-07-31 18:06:14 +08:00
fix blocked CGI read
This commit is contained in:
parent
f23d9ff3b0
commit
1de7fef760
@ -1305,7 +1305,10 @@ static int pull(FILE *fp, SOCKET sock, SSL *ssl, char *buf, int len) {
|
|||||||
if (ssl != NULL) {
|
if (ssl != NULL) {
|
||||||
nread = SSL_read(ssl, buf, len);
|
nread = SSL_read(ssl, buf, len);
|
||||||
} else if (fp != NULL) {
|
} else if (fp != NULL) {
|
||||||
nread = fread(buf, 1, (size_t) len, fp);
|
// Use read() instead of fread(), because if we're reading from the CGI
|
||||||
|
// pipe, fread() may block until IO buffer is filled up. We cannot afford
|
||||||
|
// to block and must pass all read bytes immediately to the client.
|
||||||
|
nread = read(fileno(fp), buf, (size_t) len);
|
||||||
if (ferror(fp))
|
if (ferror(fp))
|
||||||
nread = -1;
|
nread = -1;
|
||||||
} else {
|
} else {
|
||||||
|
19
test/test.pl
19
test/test.pl
@ -59,13 +59,11 @@ sub req {
|
|||||||
last unless print $sock $byte;
|
last unless print $sock $byte;
|
||||||
select undef, undef, undef, .001 if length($request) < 256;
|
select undef, undef, undef, .001 if length($request) < 256;
|
||||||
}
|
}
|
||||||
my $out = '';
|
my ($out, $buf) = ('', '');
|
||||||
eval {
|
eval {
|
||||||
alarm $timeout if $timeout;
|
alarm $timeout if $timeout;
|
||||||
foreach (<$sock>) {
|
$out .= $buf while (sysread($sock, $buf, 1024) > 0);
|
||||||
$out .= $_;
|
alarm 0 if $timeout;
|
||||||
}
|
|
||||||
alarm 0;
|
|
||||||
};
|
};
|
||||||
close $sock;
|
close $sock;
|
||||||
|
|
||||||
@ -182,6 +180,14 @@ o("GET /hello.txt HTTP/1.0\n\n", 'Content-Length: 17\s',
|
|||||||
o("GET /%68%65%6c%6c%6f%2e%74%78%74 HTTP/1.0\n\n",
|
o("GET /%68%65%6c%6c%6f%2e%74%78%74 HTTP/1.0\n\n",
|
||||||
'HTTP/1.1 200 OK', 'URL-decoding');
|
'HTTP/1.1 200 OK', 'URL-decoding');
|
||||||
|
|
||||||
|
# Break CGI reading after 1 second. We must get full output.
|
||||||
|
# Since CGI script does sleep, we sleep as well and increase request count
|
||||||
|
# manually.
|
||||||
|
fail('Slow CGI output forward ') unless
|
||||||
|
req("GET /timeout.cgi HTTP/1.0\r\n\r\n", 0, 1) =~ /Some data/s;
|
||||||
|
sleep 3;
|
||||||
|
$num_requests++;
|
||||||
|
|
||||||
# '+' in URI must not be URL-decoded to space
|
# '+' in URI must not be URL-decoded to space
|
||||||
write_file("$root/a+.txt", '');
|
write_file("$root/a+.txt", '');
|
||||||
o("GET /a+.txt HTTP/1.0\n\n", 'HTTP/1.1 200 OK', 'URL-decoding, + in URI');
|
o("GET /a+.txt HTTP/1.0\n\n", 'HTTP/1.1 200 OK', 'URL-decoding, + in URI');
|
||||||
@ -225,9 +231,6 @@ o("GET /ta/x/ HTTP/1.0\n\n", "SCRIPT_NAME=/ta/x/index.cgi",
|
|||||||
# 'HTTP/1.1 200.+keep-alive.+HTTP/1.1 200.+close',
|
# 'HTTP/1.1 200.+keep-alive.+HTTP/1.1 200.+close',
|
||||||
# 'Request pipelining', 2);
|
# 'Request pipelining', 2);
|
||||||
|
|
||||||
fail('Slow CGI output forward ') unless
|
|
||||||
req("GET /timeout.cgi HTTP/1.0\r\n\r\n", 1, 1) =~ /Some data/gs;
|
|
||||||
|
|
||||||
my $mime_types = {
|
my $mime_types = {
|
||||||
html => 'text/html',
|
html => 'text/html',
|
||||||
htm => 'text/html',
|
htm => 'text/html',
|
||||||
|
@ -1,16 +1,11 @@
|
|||||||
#!/usr/bin/env perl
|
#!/usr/bin/env perl
|
||||||
|
|
||||||
use Cwd;
|
# Make stdout unbuffered
|
||||||
use CGI;
|
$| = 1;
|
||||||
|
|
||||||
use vars '%in';
|
|
||||||
CGI::ReadParse();
|
|
||||||
|
|
||||||
print "Content-Type: text/html\r\n\r\n";
|
|
||||||
|
|
||||||
# This script outputs some content, then sleeps for 5 seconds, then exits.
|
# This script outputs some content, then sleeps for 5 seconds, then exits.
|
||||||
# Web server should return the content immediately after it is sent,
|
# Web server should return the content immediately after it is sent,
|
||||||
# not waiting until the script exits.
|
# not waiting until the script exits.
|
||||||
|
print "Content-Type: text/html\r\n\r\n";
|
||||||
print "Some data";
|
print "Some data";
|
||||||
flush STDOUT;
|
sleep 3;
|
||||||
sleep 5;
|
|
||||||
|
Loading…
Reference in New Issue
Block a user