bugfix: the ngx.thread API did not work in access_by_lua*.
This commit is contained in:
Родитель
f4e8894e2d
Коммит
00e99d519f
|
@ -88,11 +88,6 @@ ngx_http_lua_access_handler(ngx_http_request_t *r)
|
|||
|
||||
dd("entered? %d", (int) ctx->entered_access_phase);
|
||||
|
||||
if (ctx->waiting_more_body) {
|
||||
dd("WAITING MORE BODY");
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
if (ctx->entered_access_phase) {
|
||||
dd("calling wev handler");
|
||||
rc = ctx->resume_handler(r);
|
||||
|
@ -105,6 +100,11 @@ ngx_http_lua_access_handler(ngx_http_request_t *r)
|
|||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
if (ctx->waiting_more_body) {
|
||||
dd("WAITING MORE BODY");
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
if (llcf->force_read_body && !ctx->read_body_done) {
|
||||
r->request_body_in_single_buf = 1;
|
||||
r->request_body_in_persistent_file = 1;
|
||||
|
@ -291,12 +291,25 @@ ngx_http_lua_access_by_chunk(lua_State *L, ngx_http_request_t *r)
|
|||
}
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return ngx_http_lua_run_posted_threads(c, L, r, ctx);
|
||||
rc = ngx_http_lua_run_posted_threads(c, L, r, ctx);
|
||||
|
||||
if (rc == NGX_ERROR || rc == NGX_DONE || rc >= NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
if (rc == NGX_DONE) {
|
||||
ngx_http_finalize_request(r, NGX_DONE);
|
||||
return ngx_http_lua_run_posted_threads(c, L, r, ctx);
|
||||
|
||||
rc = ngx_http_lua_run_posted_threads(c, L, r, ctx);
|
||||
|
||||
if (rc == NGX_ERROR || rc == NGX_DONE || rc >= NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
return NGX_DECLINED;
|
||||
|
|
|
@ -0,0 +1,343 @@
|
|||
# vim:set ft= ts=4 sw=4 et fdm=marker:
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx::Socket;
|
||||
use t::StapThread;
|
||||
|
||||
our $GCScript = $t::StapThread::GCScript;
|
||||
our $StapScript = $t::StapThread::StapScript;
|
||||
|
||||
repeat_each(2);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4);
|
||||
|
||||
$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
|
||||
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= '11211';
|
||||
|
||||
#no_shuffle();
|
||||
no_long_string();
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: exec in user thread (entry still pending)
|
||||
--- config
|
||||
location /lua {
|
||||
access_by_lua '
|
||||
function f()
|
||||
ngx.exec("/foo")
|
||||
end
|
||||
|
||||
ngx.thread.spawn(f)
|
||||
ngx.sleep(1)
|
||||
ngx.say("hello")
|
||||
';
|
||||
content_by_lua return;
|
||||
}
|
||||
|
||||
location /foo {
|
||||
echo i am foo;
|
||||
}
|
||||
--- request
|
||||
GET /lua
|
||||
--- stap2 eval: $::StapScript
|
||||
--- stap eval: $::GCScript
|
||||
--- stap_out
|
||||
create 2 in 1
|
||||
create user thread 2 in 1
|
||||
delete thread 2
|
||||
delete thread 1
|
||||
|
||||
--- response_body
|
||||
i am foo
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: exec in user thread (entry already quits)
|
||||
--- config
|
||||
location /lua {
|
||||
access_by_lua '
|
||||
function f()
|
||||
ngx.sleep(0.1)
|
||||
ngx.exec("/foo")
|
||||
end
|
||||
|
||||
ngx.thread.spawn(f)
|
||||
';
|
||||
content_by_lua return;
|
||||
}
|
||||
|
||||
location /foo {
|
||||
echo i am foo;
|
||||
}
|
||||
--- request
|
||||
GET /lua
|
||||
--- stap2 eval: $::StapScript
|
||||
--- stap eval: $::GCScript
|
||||
--- stap_out
|
||||
create 2 in 1
|
||||
create user thread 2 in 1
|
||||
delete thread 1
|
||||
delete thread 2
|
||||
|
||||
--- response_body
|
||||
i am foo
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 3: exec in user thread (entry thread is still pending on ngx.sleep)
|
||||
--- config
|
||||
location /lua {
|
||||
access_by_lua '
|
||||
function f()
|
||||
ngx.sleep(0.1)
|
||||
ngx.exec("/foo")
|
||||
end
|
||||
|
||||
ngx.thread.spawn(f)
|
||||
ngx.sleep(1)
|
||||
';
|
||||
content_by_lua return;
|
||||
}
|
||||
|
||||
location = /foo {
|
||||
echo hello foo;
|
||||
}
|
||||
--- request
|
||||
GET /lua
|
||||
--- stap2 eval: $::StapScript
|
||||
--- stap eval
|
||||
<<'_EOC_' . $::GCScript;
|
||||
|
||||
global timers
|
||||
|
||||
F(ngx_http_free_request) {
|
||||
println("free request")
|
||||
}
|
||||
|
||||
M(timer-add) {
|
||||
if ($arg2 == 1000 || $arg2 == 100) {
|
||||
timers[$arg1] = $arg2
|
||||
printf("add timer %d\n", $arg2)
|
||||
}
|
||||
}
|
||||
|
||||
M(timer-del) {
|
||||
tm = timers[$arg1]
|
||||
if (tm == 1000 || tm == 100) {
|
||||
printf("delete timer %d\n", tm)
|
||||
delete timers[$arg1]
|
||||
}
|
||||
/*
|
||||
if (tm == 1000) {
|
||||
print_ubacktrace()
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
M(timer-expire) {
|
||||
tm = timers[$arg1]
|
||||
if (tm == 1000 || tm == 100) {
|
||||
printf("expire timer %d\n", timers[$arg1])
|
||||
delete timers[$arg1]
|
||||
}
|
||||
}
|
||||
|
||||
F(ngx_http_lua_sleep_cleanup) {
|
||||
println("lua sleep cleanup")
|
||||
}
|
||||
_EOC_
|
||||
|
||||
--- stap_out
|
||||
create 2 in 1
|
||||
create user thread 2 in 1
|
||||
add timer 100
|
||||
add timer 1000
|
||||
expire timer 100
|
||||
lua sleep cleanup
|
||||
delete timer 1000
|
||||
delete thread 2
|
||||
delete thread 1
|
||||
free request
|
||||
|
||||
--- response_body
|
||||
hello foo
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 4: exec in a user thread (another user thread is still pending on ngx.sleep)
|
||||
--- config
|
||||
location /lua {
|
||||
access_by_lua '
|
||||
function f()
|
||||
ngx.sleep(0.1)
|
||||
ngx.exec("/foo")
|
||||
end
|
||||
|
||||
function g()
|
||||
ngx.sleep(1)
|
||||
end
|
||||
|
||||
ngx.thread.spawn(f)
|
||||
ngx.thread.spawn(g)
|
||||
';
|
||||
content_by_lua return;
|
||||
}
|
||||
|
||||
location = /foo {
|
||||
echo hello foo;
|
||||
}
|
||||
--- request
|
||||
GET /lua
|
||||
--- stap2 eval: $::StapScript
|
||||
--- stap eval
|
||||
<<'_EOC_' . $::GCScript;
|
||||
|
||||
global timers
|
||||
|
||||
F(ngx_http_free_request) {
|
||||
println("free request")
|
||||
}
|
||||
|
||||
M(timer-add) {
|
||||
if ($arg2 == 1000 || $arg2 == 100) {
|
||||
timers[$arg1] = $arg2
|
||||
printf("add timer %d\n", $arg2)
|
||||
}
|
||||
}
|
||||
|
||||
M(timer-del) {
|
||||
tm = timers[$arg1]
|
||||
if (tm == 1000 || tm == 100) {
|
||||
printf("delete timer %d\n", tm)
|
||||
delete timers[$arg1]
|
||||
}
|
||||
/*
|
||||
if (tm == 1000) {
|
||||
print_ubacktrace()
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
M(timer-expire) {
|
||||
tm = timers[$arg1]
|
||||
if (tm == 1000 || tm == 100) {
|
||||
printf("expire timer %d\n", timers[$arg1])
|
||||
delete timers[$arg1]
|
||||
}
|
||||
}
|
||||
|
||||
F(ngx_http_lua_sleep_cleanup) {
|
||||
println("lua sleep cleanup")
|
||||
}
|
||||
_EOC_
|
||||
|
||||
--- stap_out
|
||||
create 2 in 1
|
||||
create user thread 2 in 1
|
||||
add timer 100
|
||||
create 3 in 1
|
||||
create user thread 3 in 1
|
||||
add timer 1000
|
||||
delete thread 1
|
||||
expire timer 100
|
||||
lua sleep cleanup
|
||||
delete timer 1000
|
||||
delete thread 2
|
||||
delete thread 3
|
||||
free request
|
||||
|
||||
--- response_body
|
||||
hello foo
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 5: exec in user thread (entry thread is still pending on ngx.location.capture), without pending output
|
||||
--- config
|
||||
location /lua {
|
||||
client_body_timeout 12000ms;
|
||||
access_by_lua '
|
||||
function f()
|
||||
ngx.sleep(0.1)
|
||||
ngx.exec("/foo")
|
||||
end
|
||||
|
||||
ngx.thread.spawn(f)
|
||||
|
||||
ngx.location.capture("/sleep")
|
||||
ngx.say("end")
|
||||
';
|
||||
content_by_lua return;
|
||||
}
|
||||
|
||||
location = /sleep {
|
||||
echo_sleep 0.2;
|
||||
}
|
||||
|
||||
location = /foo {
|
||||
echo hello world;
|
||||
}
|
||||
--- request
|
||||
POST /lua
|
||||
--- more_headers
|
||||
Content-Length: 1024
|
||||
--- stap2 eval: $::StapScript
|
||||
--- stap eval
|
||||
<<'_EOC_' . $::GCScript;
|
||||
|
||||
global timers
|
||||
|
||||
F(ngx_http_free_request) {
|
||||
println("free request")
|
||||
}
|
||||
|
||||
M(timer-add) {
|
||||
if ($arg2 == 200 || $arg2 == 100) {
|
||||
timers[$arg1] = $arg2
|
||||
printf("add timer %d\n", $arg2)
|
||||
}
|
||||
}
|
||||
|
||||
M(timer-del) {
|
||||
tm = timers[$arg1]
|
||||
if (tm == 200 || tm == 100) {
|
||||
printf("delete timer %d\n", tm)
|
||||
delete timers[$arg1]
|
||||
}
|
||||
}
|
||||
|
||||
M(timer-expire) {
|
||||
tm = timers[$arg1]
|
||||
if (tm == 200 || tm == 100) {
|
||||
printf("expire timer %d\n", timers[$arg1])
|
||||
delete timers[$arg1]
|
||||
}
|
||||
}
|
||||
_EOC_
|
||||
|
||||
--- stap_out
|
||||
create 2 in 1
|
||||
create user thread 2 in 1
|
||||
add timer 100
|
||||
add timer 200
|
||||
expire timer 100
|
||||
delete thread 2
|
||||
delete thread 1
|
||||
delete timer 200
|
||||
free request
|
||||
|
||||
--- ignore_response
|
||||
--- error_log
|
||||
attempt to abort with pending subrequests
|
||||
--- no_error_log
|
||||
[alert]
|
||||
[warn]
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,191 @@
|
|||
# vim:set ft= ts=4 sw=4 et fdm=marker:
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx::Socket;
|
||||
use t::StapThread;
|
||||
|
||||
our $GCScript = $t::StapThread::GCScript;
|
||||
our $StapScript = $t::StapThread::StapScript;
|
||||
|
||||
repeat_each(2);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4);
|
||||
|
||||
$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
|
||||
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= '11211';
|
||||
$ENV{TEST_NGINX_REDIS_PORT} ||= '6379';
|
||||
|
||||
#no_shuffle();
|
||||
no_long_string();
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: ngx.redirect() in user thread (entry thread is still pending on ngx.location.capture_multi), without pending output
|
||||
--- config
|
||||
location /lua {
|
||||
client_body_timeout 12000ms;
|
||||
access_by_lua '
|
||||
function f()
|
||||
ngx.sleep(0.1)
|
||||
ngx.redirect(301)
|
||||
end
|
||||
|
||||
ngx.thread.spawn(f)
|
||||
|
||||
ngx.location.capture_multi{
|
||||
{"/echo"},
|
||||
{"/sleep"}
|
||||
}
|
||||
ngx.say("end")
|
||||
';
|
||||
content_by_lua return;
|
||||
}
|
||||
|
||||
location = /echo {
|
||||
echo hello;
|
||||
}
|
||||
|
||||
location = /sleep {
|
||||
echo_sleep 0.2;
|
||||
}
|
||||
--- request
|
||||
POST /lua
|
||||
--- more_headers
|
||||
Content-Length: 1024
|
||||
--- stap2 eval: $::StapScript
|
||||
--- stap eval
|
||||
<<'_EOC_' . $::GCScript;
|
||||
|
||||
global timers
|
||||
|
||||
F(ngx_http_free_request) {
|
||||
println("free request")
|
||||
}
|
||||
|
||||
M(timer-add) {
|
||||
if ($arg2 == 200 || $arg2 == 100) {
|
||||
timers[$arg1] = $arg2
|
||||
printf("add timer %d\n", $arg2)
|
||||
}
|
||||
}
|
||||
|
||||
M(timer-del) {
|
||||
tm = timers[$arg1]
|
||||
if (tm == 200 || tm == 100) {
|
||||
printf("delete timer %d\n", tm)
|
||||
delete timers[$arg1]
|
||||
}
|
||||
}
|
||||
|
||||
M(timer-expire) {
|
||||
tm = timers[$arg1]
|
||||
if (tm == 200 || tm == 100) {
|
||||
printf("expire timer %d\n", timers[$arg1])
|
||||
delete timers[$arg1]
|
||||
}
|
||||
}
|
||||
|
||||
F(ngx_http_lua_post_subrequest) {
|
||||
printf("post subreq %s\n", ngx_http_req_uri($r))
|
||||
}
|
||||
_EOC_
|
||||
|
||||
--- stap_out
|
||||
create 2 in 1
|
||||
create user thread 2 in 1
|
||||
add timer 100
|
||||
post subreq /echo
|
||||
add timer 200
|
||||
expire timer 100
|
||||
delete thread 2
|
||||
delete thread 1
|
||||
delete timer 200
|
||||
free request
|
||||
|
||||
--- ignore_response
|
||||
--- error_log
|
||||
attempt to abort with pending subrequests
|
||||
--- no_error_log
|
||||
[alert]
|
||||
[warn]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: redirect in user thread (entry thread is still pending on ngx.sleep)
|
||||
--- config
|
||||
location /lua {
|
||||
access_by_lua '
|
||||
function f()
|
||||
ngx.sleep(0.1)
|
||||
ngx.redirect(301)
|
||||
end
|
||||
|
||||
ngx.thread.spawn(f)
|
||||
ngx.sleep(1)
|
||||
ngx.say("end")
|
||||
';
|
||||
content_by_lua return;
|
||||
}
|
||||
--- request
|
||||
GET /lua
|
||||
--- stap2 eval: $::StapScript
|
||||
--- stap eval
|
||||
<<'_EOC_' . $::GCScript;
|
||||
|
||||
global timers
|
||||
|
||||
F(ngx_http_free_request) {
|
||||
println("free request")
|
||||
}
|
||||
|
||||
M(timer-add) {
|
||||
if ($arg2 == 1000 || $arg2 == 100) {
|
||||
timers[$arg1] = $arg2
|
||||
printf("add timer %d\n", $arg2)
|
||||
}
|
||||
}
|
||||
|
||||
M(timer-del) {
|
||||
tm = timers[$arg1]
|
||||
if (tm == 1000 || tm == 100) {
|
||||
printf("delete timer %d\n", tm)
|
||||
delete timers[$arg1]
|
||||
}
|
||||
/*
|
||||
if (tm == 1000) {
|
||||
print_ubacktrace()
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
M(timer-expire) {
|
||||
tm = timers[$arg1]
|
||||
if (tm == 1000 || tm == 100) {
|
||||
printf("expire timer %d\n", timers[$arg1])
|
||||
delete timers[$arg1]
|
||||
}
|
||||
}
|
||||
|
||||
F(ngx_http_lua_sleep_cleanup) {
|
||||
println("lua sleep cleanup")
|
||||
}
|
||||
_EOC_
|
||||
|
||||
--- stap_out
|
||||
create 2 in 1
|
||||
create user thread 2 in 1
|
||||
add timer 100
|
||||
add timer 1000
|
||||
expire timer 100
|
||||
lua sleep cleanup
|
||||
delete timer 1000
|
||||
delete thread 2
|
||||
delete thread 1
|
||||
free request
|
||||
|
||||
--- response_body_like: 302 Found
|
||||
--- error_code: 302
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче