2198 строки
44 KiB
Plaintext
2198 строки
44 KiB
Plaintext
# vim:set ft= ts=4 sw=4 et fdm=marker:
|
|
use Test::Nginx::Socket::Lua;
|
|
use t::StapThread;
|
|
|
|
our $GCScript = $t::StapThread::GCScript;
|
|
our $StapScript = $t::StapThread::StapScript;
|
|
|
|
#worker_connections(1014);
|
|
#master_on();
|
|
#workers(2);
|
|
#log_level('warn');
|
|
|
|
repeat_each(2);
|
|
|
|
plan tests => repeat_each() * (blocks() * 8 + 72);
|
|
|
|
#no_diff();
|
|
no_long_string();
|
|
|
|
our $HtmlDir = html_dir;
|
|
|
|
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
|
|
$ENV{TEST_NGINX_HTML_DIR} = $HtmlDir;
|
|
|
|
worker_connections(1024);
|
|
run_tests();
|
|
|
|
__DATA__
|
|
|
|
=== TEST 1: simple at
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local begin = ngx.now()
|
|
local function f(premature)
|
|
print("elapsed: ", ngx.now() - begin)
|
|
print("timer prematurely expired: ", premature)
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
timer prematurely expired: true
|
|
|
|
--- error_log eval
|
|
[
|
|
qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.0(?:4[4-9]|5[0-6])\d*, context: ngx\.timer, client: \d+\.\d+\.\d+\.\d+, server: 0\.0\.0\.0:\d+/,
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
"timer prematurely expired: false",
|
|
]
|
|
|
|
|
|
|
|
=== TEST 2: separated global env
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local begin = ngx.now()
|
|
local function f()
|
|
foo = 3
|
|
print("elapsed: ", ngx.now() - begin)
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
ngx.sleep(0.06)
|
|
ngx.say("foo = ", foo)
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
--- stap2
|
|
F(ngx_http_lua_timer_handler) {
|
|
println("lua timer handler")
|
|
}
|
|
|
|
--- response_body
|
|
registered timer
|
|
foo = nil
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.0(?:4[4-9]|5[0-6])/,
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection"
|
|
]
|
|
|
|
|
|
|
|
=== TEST 3: lua variable sharing via upvalue
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local begin = ngx.now()
|
|
local foo
|
|
local function f()
|
|
foo = 3
|
|
print("elapsed: ", ngx.now() - begin)
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
ngx.sleep(0.06)
|
|
ngx.say("foo = ", foo)
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
--- stap2
|
|
F(ngx_http_lua_timer_handler) {
|
|
println("lua timer handler")
|
|
}
|
|
|
|
--- response_body
|
|
registered timer
|
|
foo = 3
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.0(?:4[4-9]|5[0-6])/,
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection"
|
|
]
|
|
|
|
|
|
|
|
=== TEST 4: simple at (sleep in the timer callback)
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local begin = ngx.now()
|
|
local function f()
|
|
print("my lua timer handler")
|
|
ngx.sleep(0.02)
|
|
print("elapsed: ", ngx.now() - begin)
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.12
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
qr/\[lua\] .*? my lua timer handler/,
|
|
qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.0(?:6[4-9]|7[0-6])/,
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection"
|
|
]
|
|
|
|
|
|
|
|
=== TEST 5: tcp cosocket in timer handler (short connections)
|
|
--- config
|
|
server_tokens off;
|
|
location = /t {
|
|
content_by_lua '
|
|
local begin = ngx.now()
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
local function f()
|
|
print("my lua timer handler")
|
|
local sock = ngx.socket.tcp()
|
|
local port = $TEST_NGINX_SERVER_PORT
|
|
local ok, err = sock:connect("127.0.0.1", port)
|
|
if not ok then
|
|
fail("failed to connect: ", err)
|
|
return
|
|
end
|
|
|
|
print("connected: ", ok)
|
|
|
|
local req = "GET /foo HTTP/1.0\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n"
|
|
-- req = "OK"
|
|
|
|
local bytes, err = sock:send(req)
|
|
if not bytes then
|
|
fail("failed to send request: ", err)
|
|
return
|
|
end
|
|
|
|
print("request sent: ", bytes)
|
|
|
|
while true do
|
|
local line, err, part = sock:receive()
|
|
if line then
|
|
print("received: ", line)
|
|
|
|
else
|
|
if err == "closed" then
|
|
break
|
|
end
|
|
fail("failed to receive a line: ", err, " [", part, "]")
|
|
break
|
|
end
|
|
end
|
|
|
|
ok, err = sock:close()
|
|
print("close: ", ok, " ", err)
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
';
|
|
}
|
|
|
|
location = /foo {
|
|
content_by_lua 'ngx.say("foo")';
|
|
more_clear_headers Date;
|
|
}
|
|
|
|
--- request
|
|
GET /t
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.2
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
qr/\[lua\] .*? my lua timer handler/,
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
"connected: 1",
|
|
"request sent: 57",
|
|
"received: HTTP/1.1 200 OK",
|
|
qr/received: Server: \S+/,
|
|
"received: Content-Type: text/plain",
|
|
"received: Content-Length: 4",
|
|
"received: Connection: close",
|
|
"received: foo",
|
|
"close: 1 nil",
|
|
]
|
|
|
|
|
|
|
|
=== TEST 6: tcp cosocket in timer handler (keep-alive connections)
|
|
--- http_config eval
|
|
"lua_package_path '$::HtmlDir/?.lua;./?.lua';"
|
|
|
|
--- config
|
|
location = /t {
|
|
content_by_lua '
|
|
local begin = ngx.now()
|
|
local function f()
|
|
print("my lua timer handler")
|
|
|
|
local test = require "test"
|
|
local port = $TEST_NGINX_MEMCACHED_PORT
|
|
test.go(port)
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
';
|
|
}
|
|
|
|
--- user_files
|
|
>>> test.lua
|
|
module("test", package.seeall)
|
|
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
|
|
function go(port)
|
|
local sock = ngx.socket.tcp()
|
|
local ok, err = sock:connect("127.0.0.1", port)
|
|
if not ok then
|
|
fail("failed to connect: ", err)
|
|
return
|
|
end
|
|
|
|
print("connected: ", ok, ", reused: ", sock:getreusedtimes())
|
|
|
|
local req = "flush_all\r\n"
|
|
|
|
local bytes, err = sock:send(req)
|
|
if not bytes then
|
|
fail("failed to send request: ", err)
|
|
return
|
|
end
|
|
print("request sent: ", bytes)
|
|
|
|
local line, err, part = sock:receive()
|
|
if line then
|
|
print("received: ", line)
|
|
|
|
else
|
|
fail("failed to receive a line: ", err, " [", part, "]")
|
|
end
|
|
|
|
local ok, err = sock:setkeepalive()
|
|
if not ok then
|
|
fail("failed to set reusable: ", err)
|
|
end
|
|
end
|
|
|
|
--- request
|
|
GET /t
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.2
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
qr/\[lua\] .*? my lua timer handler/,
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
qr/go\(\): connected: 1, reused: \d+/,
|
|
"go(): request sent: 11",
|
|
"go(): received: OK",
|
|
]
|
|
|
|
|
|
|
|
=== TEST 7: 0 timer
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local begin = ngx.now()
|
|
local function f()
|
|
print("elapsed: ", ngx.now() - begin)
|
|
end
|
|
local ok, err = ngx.timer.at(0, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.2
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0(?:[^.]|\.00)/,
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection"
|
|
]
|
|
|
|
|
|
|
|
=== TEST 8: udp cosocket in timer handler
|
|
--- config
|
|
location = /t {
|
|
content_by_lua '
|
|
local begin = ngx.now()
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
local function f()
|
|
print("my lua timer handler")
|
|
local socket = ngx.socket
|
|
-- local socket = require "socket"
|
|
|
|
local udp = socket.udp()
|
|
|
|
local port = $TEST_NGINX_MEMCACHED_PORT
|
|
udp:settimeout(1000) -- 1 sec
|
|
|
|
local ok, err = udp:setpeername("127.0.0.1", port)
|
|
if not ok then
|
|
fail("failed to connect: ", err)
|
|
return
|
|
end
|
|
|
|
print("connected: ", ok)
|
|
|
|
local req = "\\0\\1\\0\\0\\0\\1\\0\\0flush_all\\r\\n"
|
|
local ok, err = udp:send(req)
|
|
if not ok then
|
|
fail("failed to send: ", err)
|
|
return
|
|
end
|
|
|
|
local data, err = udp:receive()
|
|
if not data then
|
|
fail("failed to receive data: ", err)
|
|
return
|
|
end
|
|
print("received ", #data, " bytes: ", data)
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
';
|
|
}
|
|
|
|
location = /foo {
|
|
content_by_lua 'ngx.say("foo")';
|
|
more_clear_headers Date;
|
|
}
|
|
|
|
--- request
|
|
GET /t
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.2
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
qr/\[lua\] .*? my lua timer handler/,
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
"connected: 1",
|
|
"received 12 bytes: \x{00}\x{01}\x{00}\x{00}\x{00}\x{01}\x{00}\x{00}OK\x{0d}\x{0a}"
|
|
]
|
|
|
|
|
|
|
|
=== TEST 9: simple at (sleep in the timer callback) - log_by_lua
|
|
--- config
|
|
location /t {
|
|
echo hello world;
|
|
log_by_lua '
|
|
local begin = ngx.now()
|
|
local function f()
|
|
print("my lua timer handler")
|
|
ngx.sleep(0.02)
|
|
print("elapsed: ", ngx.now() - begin)
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, f)
|
|
if not ok then
|
|
ngx.log(ngx.ERR, "failed to set timer: ", err)
|
|
return
|
|
end
|
|
print("registered timer")
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
|
|
--- response_body
|
|
hello world
|
|
|
|
--- wait: 0.12
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
"registered timer",
|
|
qr/\[lua\] .*? my lua timer handler/,
|
|
qr/\[lua\] log_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.0(?:6[4-9]|7[0-6])/,
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection"
|
|
]
|
|
|
|
|
|
|
|
=== TEST 10: tcp cosocket in timer handler (keep-alive connections) - log_by_lua
|
|
--- http_config eval
|
|
"lua_package_path '$::HtmlDir/?.lua;./?.lua';"
|
|
|
|
--- config
|
|
location = /t {
|
|
echo hello;
|
|
log_by_lua '
|
|
local begin = ngx.now()
|
|
local function f()
|
|
print("my lua timer handler")
|
|
|
|
local test = require "test"
|
|
local port = $TEST_NGINX_MEMCACHED_PORT
|
|
test.go(port)
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, f)
|
|
if not ok then
|
|
ngx.log(ngx.ERR, "failed to set timer: ", err)
|
|
return
|
|
end
|
|
print("registered timer")
|
|
';
|
|
}
|
|
|
|
--- user_files
|
|
>>> test.lua
|
|
module("test", package.seeall)
|
|
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
|
|
function go(port)
|
|
local sock = ngx.socket.tcp()
|
|
local ok, err = sock:connect("127.0.0.1", port)
|
|
if not ok then
|
|
fail("failed to connect: ", err)
|
|
return
|
|
end
|
|
|
|
print("connected: ", ok, ", reused: ", sock:getreusedtimes())
|
|
|
|
local req = "flush_all\r\n"
|
|
|
|
local bytes, err = sock:send(req)
|
|
if not bytes then
|
|
fail("failed to send request: ", err)
|
|
return
|
|
end
|
|
print("request sent: ", bytes)
|
|
|
|
local line, err, part = sock:receive()
|
|
if line then
|
|
print("received: ", line)
|
|
|
|
else
|
|
fail("failed to receive a line: ", err, " [", part, "]")
|
|
end
|
|
|
|
local ok, err = sock:setkeepalive()
|
|
if not ok then
|
|
fail("failed to set reusable: ", err)
|
|
end
|
|
end
|
|
|
|
--- request
|
|
GET /t
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
|
|
--- response_body
|
|
hello
|
|
|
|
--- wait: 0.2
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
"registered timer",
|
|
qr/\[lua\] .*? my lua timer handler/,
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
qr/go\(\): connected: 1, reused: \d+/,
|
|
"go(): request sent: 11",
|
|
"go(): received: OK",
|
|
]
|
|
|
|
|
|
|
|
=== TEST 11: tcp cosocket in timer handler (keep-alive connections) - header_filter_by_lua
|
|
--- http_config eval
|
|
"lua_package_path '$::HtmlDir/?.lua;./?.lua';"
|
|
|
|
--- config
|
|
location = /t {
|
|
echo hello;
|
|
header_filter_by_lua '
|
|
local begin = ngx.now()
|
|
local function f()
|
|
print("my lua timer handler")
|
|
|
|
local test = require "test"
|
|
local port = $TEST_NGINX_MEMCACHED_PORT
|
|
test.go(port)
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, f)
|
|
if not ok then
|
|
ngx.log(ngx.ERR, "failed to set timer: ", err)
|
|
return
|
|
end
|
|
print("registered timer")
|
|
';
|
|
}
|
|
|
|
--- user_files
|
|
>>> test.lua
|
|
module("test", package.seeall)
|
|
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
|
|
function go(port)
|
|
local sock = ngx.socket.tcp()
|
|
local ok, err = sock:connect("127.0.0.1", port)
|
|
if not ok then
|
|
fail("failed to connect: ", err)
|
|
return
|
|
end
|
|
|
|
print("connected: ", ok, ", reused: ", sock:getreusedtimes())
|
|
|
|
local req = "flush_all\r\n"
|
|
|
|
local bytes, err = sock:send(req)
|
|
if not bytes then
|
|
fail("failed to send request: ", err)
|
|
return
|
|
end
|
|
print("request sent: ", bytes)
|
|
|
|
local line, err, part = sock:receive()
|
|
if line then
|
|
print("received: ", line)
|
|
|
|
else
|
|
fail("failed to receive a line: ", err, " [", part, "]")
|
|
end
|
|
|
|
local ok, err = sock:setkeepalive()
|
|
if not ok then
|
|
fail("failed to set reusable: ", err)
|
|
end
|
|
end
|
|
|
|
--- request
|
|
GET /t
|
|
--- stap2 eval: $::StapScript
|
|
--- stap3
|
|
global count = 0
|
|
F(ngx_http_lua_header_filter) {
|
|
if (count++ == 10) {
|
|
println("header filter")
|
|
print_ubacktrace()
|
|
}
|
|
}
|
|
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
|
|
--- response_body
|
|
hello
|
|
|
|
--- wait: 0.2
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
"registered timer",
|
|
qr/\[lua\] .*? my lua timer handler/,
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
qr/go\(\): connected: 1, reused: \d+/,
|
|
"go(): request sent: 11",
|
|
"go(): received: OK",
|
|
]
|
|
|
|
|
|
|
|
=== TEST 12: tcp cosocket in timer handler (keep-alive connections) - body_filter_by_lua
|
|
--- http_config eval
|
|
"lua_package_path '$::HtmlDir/?.lua;./?.lua';"
|
|
|
|
--- config
|
|
location = /t {
|
|
echo hello;
|
|
body_filter_by_lua '
|
|
local begin = ngx.now()
|
|
local function f()
|
|
print("my lua timer handler")
|
|
|
|
local test = require "test"
|
|
local port = $TEST_NGINX_MEMCACHED_PORT
|
|
test.go(port)
|
|
end
|
|
local ok, err = ngx.timer.at(0.01, f)
|
|
if not ok then
|
|
ngx.log(ngx.ERR, "failed to set timer: ", err)
|
|
return
|
|
end
|
|
print("registered timer")
|
|
';
|
|
}
|
|
|
|
--- user_files
|
|
>>> test.lua
|
|
module("test", package.seeall)
|
|
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
|
|
function go(port)
|
|
local sock = ngx.socket.tcp()
|
|
local ok, err = sock:connect("127.0.0.1", port)
|
|
if not ok then
|
|
fail("failed to connect: ", err)
|
|
return
|
|
end
|
|
|
|
print("connected: ", ok, ", reused: ", sock:getreusedtimes())
|
|
|
|
local req = "flush_all\r\n"
|
|
|
|
local bytes, err = sock:send(req)
|
|
if not bytes then
|
|
fail("failed to send request: ", err)
|
|
return
|
|
end
|
|
print("request sent: ", bytes)
|
|
|
|
local line, err, part = sock:receive()
|
|
if line then
|
|
print("received: ", line)
|
|
|
|
else
|
|
fail("failed to receive a line: ", err, " [", part, "]")
|
|
end
|
|
|
|
local ok, err = sock:setkeepalive()
|
|
if not ok then
|
|
fail("failed to set keep alive: ", err)
|
|
end
|
|
end
|
|
|
|
--- request
|
|
GET /t
|
|
--- stap2 eval: $::StapScript
|
|
--- stap3
|
|
global count = 0
|
|
F(ngx_http_lua_header_filter) {
|
|
if (count++ == 10) {
|
|
println("header filter")
|
|
print_ubacktrace()
|
|
}
|
|
}
|
|
|
|
--- stap eval: $::GCScript
|
|
--- stap_out_like chop
|
|
create 2 in 1
|
|
create 3 in 1
|
|
(?:terminate 2: ok
|
|
delete thread 2
|
|
terminate 3: ok
|
|
delete thread 3
|
|
|terminate 3: ok
|
|
delete thread 3
|
|
terminate 2: ok
|
|
delete thread 2)$
|
|
|
|
--- response_body
|
|
hello
|
|
|
|
--- wait: 0.2
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
"registered timer",
|
|
qr/\[lua\] .*? my lua timer handler/,
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
qr/go\(\): connected: 1, reused: \d+/,
|
|
"go(): request sent: 11",
|
|
"go(): received: OK",
|
|
]
|
|
|
|
|
|
|
|
=== TEST 13: tcp cosocket in timer handler (keep-alive connections) - set_by_lua
|
|
--- http_config eval
|
|
"lua_package_path '$::HtmlDir/?.lua;./?.lua';"
|
|
|
|
--- config
|
|
location = /t {
|
|
set_by_lua $a '
|
|
local begin = ngx.now()
|
|
local function f()
|
|
print("my lua timer handler")
|
|
|
|
local test = require "test"
|
|
local port = $TEST_NGINX_MEMCACHED_PORT
|
|
test.go(port)
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, f)
|
|
if not ok then
|
|
ngx.log(ngx.ERR, "failed to set timer: ", err)
|
|
return
|
|
end
|
|
print("registered timer")
|
|
return 32
|
|
';
|
|
echo $a;
|
|
}
|
|
|
|
--- user_files
|
|
>>> test.lua
|
|
module("test", package.seeall)
|
|
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
|
|
function go(port)
|
|
local sock = ngx.socket.tcp()
|
|
local ok, err = sock:connect("127.0.0.1", port)
|
|
if not ok then
|
|
fail("failed to connect: ", err)
|
|
return
|
|
end
|
|
|
|
print("connected: ", ok, ", reused: ", sock:getreusedtimes())
|
|
|
|
local req = "flush_all\r\n"
|
|
|
|
local bytes, err = sock:send(req)
|
|
if not bytes then
|
|
fail("failed to send request: ", err)
|
|
return
|
|
end
|
|
print("request sent: ", bytes)
|
|
|
|
local line, err, part = sock:receive()
|
|
if line then
|
|
print("received: ", line)
|
|
|
|
else
|
|
fail("failed to receive a line: ", err, " [", part, "]")
|
|
end
|
|
|
|
local ok, err = sock:setkeepalive()
|
|
if not ok then
|
|
fail("failed to set reusable: ", err)
|
|
end
|
|
end
|
|
|
|
--- request
|
|
GET /t
|
|
--- stap2 eval: $::StapScript
|
|
--- stap3
|
|
global count = 0
|
|
F(ngx_http_lua_header_filter) {
|
|
if (count++ == 10) {
|
|
println("header filter")
|
|
print_ubacktrace()
|
|
}
|
|
}
|
|
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
|
|
--- response_body
|
|
32
|
|
|
|
--- wait: 0.2
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
"registered timer",
|
|
qr/\[lua\] .*? my lua timer handler/,
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
qr/go\(\): connected: 1, reused: \d+/,
|
|
"go(): request sent: 11",
|
|
"go(): received: OK",
|
|
]
|
|
|
|
|
|
|
|
=== TEST 14: coroutine API
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local cc, cr, cy = coroutine.create, coroutine.resume, coroutine.yield
|
|
local function f()
|
|
function f()
|
|
local cnt = 0
|
|
for i = 1, 20 do
|
|
print("cnt = ", cnt)
|
|
cy()
|
|
cnt = cnt + 1
|
|
end
|
|
end
|
|
|
|
local c = cc(f)
|
|
for i=1,3 do
|
|
cr(c)
|
|
print("after resume, i = ", i)
|
|
end
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
create 3 in 2
|
|
terminate 2: ok
|
|
delete thread 2
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
"cnt = 0",
|
|
"after resume, i = 1",
|
|
"cnt = 1",
|
|
"after resume, i = 2",
|
|
"cnt = 2",
|
|
"after resume, i = 3",
|
|
]
|
|
|
|
|
|
|
|
=== TEST 15: ngx.thread API
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local function fail (...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
local function handle()
|
|
function f()
|
|
print("hello in thread")
|
|
return "done"
|
|
end
|
|
|
|
local t, err = ngx.thread.spawn(f)
|
|
if not t then
|
|
fail("failed to spawn thread: ", err)
|
|
return
|
|
end
|
|
|
|
print("thread created: ", coroutine.status(t))
|
|
|
|
collectgarbage()
|
|
|
|
local ok, res = ngx.thread.wait(t)
|
|
if not ok then
|
|
fail("failed to run thread: ", res)
|
|
return
|
|
end
|
|
|
|
print("wait result: ", res)
|
|
end
|
|
local ok, err = ngx.timer.at(0.01, handle)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
create 3 in 2
|
|
spawn user thread 3 in 2
|
|
terminate 3: ok
|
|
delete thread 3
|
|
terminate 2: ok
|
|
delete thread 2
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
"hello in thread",
|
|
"thread created: zombie",
|
|
"wait result: done",
|
|
]
|
|
|
|
|
|
|
|
=== TEST 16: shared dict
|
|
--- http_config
|
|
lua_shared_dict dogs 1m;
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local function f()
|
|
local dogs = ngx.shared.dogs
|
|
dogs:set("foo", 32)
|
|
dogs:set("bah", 10502)
|
|
local val = dogs:get("foo")
|
|
print("get foo: ", val, " ", type(val))
|
|
val = dogs:get("bah")
|
|
print("get bah: ", val, " ", type(val))
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
"get foo: 32 number",
|
|
"get bah: 10502 number",
|
|
]
|
|
|
|
|
|
|
|
=== TEST 17: ngx.exit(0)
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local function f()
|
|
local function g()
|
|
print("BEFORE ngx.exit")
|
|
ngx.exit(0)
|
|
end
|
|
g()
|
|
print("CANNOT REACH HERE")
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
--- stap2
|
|
F(ngx_http_lua_timer_handler) {
|
|
println("lua timer handler")
|
|
}
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
"BEFORE ngx.exit",
|
|
]
|
|
--- no_error_log
|
|
CANNOT REACH HERE
|
|
API disabled
|
|
|
|
|
|
|
|
=== TEST 18: ngx.exit(403)
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local function f()
|
|
local function g()
|
|
print("BEFORE ngx.exit")
|
|
ngx.exit(403)
|
|
end
|
|
g()
|
|
print("CANNOT REACH HERE")
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
--- stap2
|
|
F(ngx_http_lua_timer_handler) {
|
|
println("lua timer handler")
|
|
}
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
CANNOT REACH HERE
|
|
API disabled
|
|
|
|
--- error_log eval
|
|
[
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
"BEFORE ngx.exit",
|
|
]
|
|
|
|
|
|
|
|
=== TEST 19: exit in user thread (entry thread is still pending on ngx.sleep)
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local function handle()
|
|
local function f()
|
|
print("hello in thread")
|
|
ngx.sleep(0.1)
|
|
ngx.exit(0)
|
|
end
|
|
|
|
print("BEFORE thread spawn")
|
|
ngx.thread.spawn(f)
|
|
print("AFTER thread spawn")
|
|
ngx.sleep(1)
|
|
print("entry thread END")
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, handle)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
--- 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_like chop
|
|
(?:create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
free request
|
|
create 3 in 2
|
|
spawn user thread 3 in 2
|
|
add timer 100
|
|
add timer 1000
|
|
expire timer 100
|
|
terminate 3: ok
|
|
delete thread 3
|
|
lua sleep cleanup
|
|
delete timer 1000
|
|
delete thread 2|create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
create 3 in 2
|
|
spawn user thread 3 in 2
|
|
add timer 100
|
|
add timer 1000
|
|
free request
|
|
expire timer 100
|
|
terminate 3: ok
|
|
delete thread 3
|
|
lua sleep cleanup
|
|
delete timer 1000
|
|
delete thread 2)$
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.2
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
API disabled
|
|
entry thread END
|
|
|
|
--- error_log eval
|
|
[
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
"BEFORE thread spawn",
|
|
"hello in thread",
|
|
"AFTER thread spawn",
|
|
]
|
|
|
|
|
|
|
|
=== TEST 20: chained timers (0 delay)
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local s = ""
|
|
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
|
|
local function g()
|
|
s = s .. "[g]"
|
|
print("trace: ", s)
|
|
end
|
|
|
|
local function f()
|
|
local ok, err = ngx.timer.at(0, g)
|
|
if not ok then
|
|
fail("failed to set timer: ", err)
|
|
return
|
|
end
|
|
s = s .. "[f]"
|
|
end
|
|
local ok, err = ngx.timer.at(0, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
s = "[m]"
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
create 3 in 2
|
|
terminate 2: ok
|
|
delete thread 2
|
|
terminate 3: ok
|
|
delete thread 3
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log eval
|
|
[
|
|
'lua ngx.timer expired',
|
|
'http lua close fake http connection',
|
|
qr/trace: \[m\]\[f\]\[g\], context: ngx\.timer, client: \d+\.\d+\.\d+\.\d+, server: 0\.0\.0\.0:\d+/,
|
|
]
|
|
|
|
|
|
|
|
=== TEST 21: chained timers (non-zero delay)
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local s = ""
|
|
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
|
|
local function g()
|
|
s = s .. "[g]"
|
|
print("trace: ", s)
|
|
end
|
|
|
|
local function f()
|
|
local ok, err = ngx.timer.at(0.01, g)
|
|
if not ok then
|
|
fail("failed to set timer: ", err)
|
|
return
|
|
end
|
|
s = s .. "[f]"
|
|
end
|
|
local ok, err = ngx.timer.at(0.01, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
s = "[m]"
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
create 3 in 2
|
|
terminate 2: ok
|
|
delete thread 2
|
|
terminate 3: ok
|
|
delete thread 3
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log
|
|
lua ngx.timer expired
|
|
http lua close fake http connection
|
|
trace: [m][f][g]
|
|
|
|
|
|
|
|
=== TEST 22: multiple parallel timers
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local s = ""
|
|
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
|
|
local function g()
|
|
s = s .. "[g]"
|
|
print("trace: ", s)
|
|
end
|
|
|
|
local function f()
|
|
s = s .. "[f]"
|
|
end
|
|
local ok, err = ngx.timer.at(0.01, f)
|
|
if not ok then
|
|
fail("failed to set timer: ", err)
|
|
return
|
|
end
|
|
local ok, err = ngx.timer.at(0.01, g)
|
|
if not ok then
|
|
fail("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
s = "[m]"
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
create 3 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
terminate 3: ok
|
|
delete thread 3
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log
|
|
lua ngx.timer expired
|
|
http lua close fake http connection
|
|
trace: [m][f][g]
|
|
|
|
|
|
|
|
=== TEST 23: lua_max_pending_timers
|
|
--- http_config
|
|
lua_max_pending_timers 1;
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local s = ""
|
|
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
|
|
local function g()
|
|
s = s .. "[g]"
|
|
print("trace: ", s)
|
|
end
|
|
|
|
local function f()
|
|
s = s .. "[f]"
|
|
end
|
|
local ok, err = ngx.timer.at(0.01, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer f: ", err)
|
|
return
|
|
end
|
|
local ok, err = ngx.timer.at(0.01, g)
|
|
if not ok then
|
|
ngx.say("failed to set timer g: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
s = "[m]"
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
|
|
--- response_body
|
|
failed to set timer g: too many pending timers
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[alert]
|
|
[crit]
|
|
[error]
|
|
|
|
--- error_log
|
|
lua ngx.timer expired
|
|
http lua close fake http connection
|
|
|
|
|
|
|
|
=== TEST 24: lua_max_pending_timers (just not exceeding)
|
|
--- http_config
|
|
lua_max_pending_timers 2;
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local s = ""
|
|
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
|
|
local function g()
|
|
s = s .. "[g]"
|
|
print("trace: ", s)
|
|
end
|
|
|
|
local function f()
|
|
s = s .. "[f]"
|
|
end
|
|
local ok, err = ngx.timer.at(0.01, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer f: ", err)
|
|
return
|
|
end
|
|
local ok, err = ngx.timer.at(0.01, g)
|
|
if not ok then
|
|
ngx.say("failed to set timer g: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
s = "[m]"
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
create 3 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
terminate 3: ok
|
|
delete thread 3
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[alert]
|
|
[crit]
|
|
[error]
|
|
|
|
--- error_log
|
|
lua ngx.timer expired
|
|
http lua close fake http connection
|
|
trace: [m][f][g]
|
|
|
|
|
|
|
|
=== TEST 25: lua_max_pending_timers - chained timers (non-zero delay) - not exceeding
|
|
--- http_config
|
|
lua_max_pending_timers 1;
|
|
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local s = ""
|
|
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
|
|
local function g()
|
|
s = s .. "[g]"
|
|
print("trace: ", s)
|
|
end
|
|
|
|
local function f()
|
|
local ok, err = ngx.timer.at(0.01, g)
|
|
if not ok then
|
|
fail("failed to set timer: ", err)
|
|
return
|
|
end
|
|
s = s .. "[f]"
|
|
end
|
|
local ok, err = ngx.timer.at(0.01, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
s = "[m]"
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
create 3 in 2
|
|
terminate 2: ok
|
|
delete thread 2
|
|
terminate 3: ok
|
|
delete thread 3
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log
|
|
lua ngx.timer expired
|
|
http lua close fake http connection
|
|
trace: [m][f][g]
|
|
|
|
|
|
|
|
=== TEST 26: lua_max_pending_timers - chained timers (zero delay) - not exceeding
|
|
--- http_config
|
|
lua_max_pending_timers 1;
|
|
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local s = ""
|
|
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
|
|
local function g()
|
|
s = s .. "[g]"
|
|
print("trace: ", s)
|
|
end
|
|
|
|
local function f()
|
|
local ok, err = ngx.timer.at(0, g)
|
|
if not ok then
|
|
fail("failed to set timer: ", err)
|
|
return
|
|
end
|
|
s = s .. "[f]"
|
|
end
|
|
local ok, err = ngx.timer.at(0, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
s = "[m]"
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
create 3 in 2
|
|
terminate 2: ok
|
|
delete thread 2
|
|
terminate 3: ok
|
|
delete thread 3
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
|
|
--- error_log
|
|
lua ngx.timer expired
|
|
http lua close fake http connection
|
|
trace: [m][f][g]
|
|
|
|
|
|
|
|
=== TEST 27: lua_max_running_timers (just not enough)
|
|
--- http_config
|
|
lua_max_running_timers 1;
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local s = ""
|
|
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
|
|
local f, g
|
|
|
|
g = function ()
|
|
ngx.sleep(0.01)
|
|
end
|
|
|
|
f = function ()
|
|
ngx.sleep(0.01)
|
|
end
|
|
local ok, err = ngx.timer.at(0, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer f: ", err)
|
|
return
|
|
end
|
|
local ok, err = ngx.timer.at(0, g)
|
|
if not ok then
|
|
ngx.say("failed to set timer g: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
s = "[m]"
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
create 3 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[crit]
|
|
[error]
|
|
|
|
--- error_log eval
|
|
[
|
|
qr/\[alert\] .*? 1 lua_max_running_timers are not enough/,
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
]
|
|
|
|
|
|
|
|
=== TEST 28: lua_max_running_timers (just enough)
|
|
--- http_config
|
|
lua_max_running_timers 2;
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local s = ""
|
|
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
|
|
local f, g
|
|
|
|
g = function ()
|
|
ngx.sleep(0.01)
|
|
end
|
|
|
|
f = function ()
|
|
ngx.sleep(0.01)
|
|
end
|
|
local ok, err = ngx.timer.at(0, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer f: ", err)
|
|
return
|
|
end
|
|
local ok, err = ngx.timer.at(0, g)
|
|
if not ok then
|
|
ngx.say("failed to set timer g: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
s = "[m]"
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
create 3 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
terminate 3: ok
|
|
delete thread 3
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[alert]
|
|
[crit]
|
|
[error]
|
|
|
|
--- error_log
|
|
lua ngx.timer expired
|
|
http lua close fake http connection
|
|
|
|
|
|
|
|
=== TEST 29: lua_max_running_timers (just enough) - 2
|
|
--- http_config
|
|
lua_max_running_timers 2;
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local s = ""
|
|
|
|
local function fail(...)
|
|
ngx.log(ngx.ERR, ...)
|
|
end
|
|
|
|
local f, g
|
|
|
|
g = function ()
|
|
ngx.timer.at(0.02, f)
|
|
ngx.sleep(0.01)
|
|
end
|
|
|
|
f = function ()
|
|
ngx.sleep(0.01)
|
|
end
|
|
local ok, err = ngx.timer.at(0, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer f: ", err)
|
|
return
|
|
end
|
|
local ok, err = ngx.timer.at(0, g)
|
|
if not ok then
|
|
ngx.say("failed to set timer g: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
s = "[m]"
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
create 3 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
create 4 in 3
|
|
terminate 2: ok
|
|
delete thread 2
|
|
terminate 3: ok
|
|
delete thread 3
|
|
terminate 4: ok
|
|
delete thread 4
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[alert]
|
|
[crit]
|
|
[error]
|
|
|
|
--- error_log
|
|
lua ngx.timer expired
|
|
http lua close fake http connection
|
|
|
|
|
|
|
|
=== TEST 30: user args
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local begin = ngx.now()
|
|
local function f(premature, a, b, c)
|
|
print("elapsed: ", ngx.now() - begin)
|
|
print("timer prematurely expired: ", premature)
|
|
print("timer user args: ", a, " ", b, " ", c)
|
|
end
|
|
local ok, err = ngx.timer.at(0.05, f, 1, "hello", true)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
';
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- stap2 eval: $::StapScript
|
|
--- stap eval: $::GCScript
|
|
--- stap_out
|
|
create 2 in 1
|
|
terminate 1: ok
|
|
delete thread 1
|
|
terminate 2: ok
|
|
delete thread 2
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
timer prematurely expired: true
|
|
|
|
--- error_log eval
|
|
[
|
|
qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.0(?:4[4-9]|5[0-6])\d*, context: ngx\.timer/,
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
"timer prematurely expired: false",
|
|
"timer user args: 1 hello true",
|
|
]
|
|
|
|
|
|
|
|
=== TEST 31: use of ngx.ctx
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local begin = ngx.now()
|
|
local function f(premature)
|
|
ngx.ctx.s = "hello"
|
|
print("elapsed: ", ngx.now() - begin)
|
|
print("timer prematurely expired: ", premature)
|
|
end
|
|
local ok, err = ngx.timer.at(0, f)
|
|
if not ok then
|
|
ngx.say("failed to set timer: ", err)
|
|
return
|
|
end
|
|
ngx.say("registered timer")
|
|
';
|
|
log_by_lua return;
|
|
}
|
|
--- request
|
|
GET /t
|
|
|
|
--- response_body
|
|
registered timer
|
|
|
|
--- wait: 0.1
|
|
--- no_error_log
|
|
[error]
|
|
[alert]
|
|
[crit]
|
|
timer prematurely expired: true
|
|
|
|
--- error_log eval
|
|
[
|
|
qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: .*?, context: ngx\.timer/,
|
|
"lua ngx.timer expired",
|
|
"http lua close fake http connection",
|
|
"timer prematurely expired: false",
|
|
"lua release ngx.ctx at ref ",
|
|
]
|
|
|
|
|
|
|
|
=== TEST 32: syslog error log
|
|
--- http_config
|
|
#error_log syslog:server=127.0.0.1:12345 error;
|
|
--- config
|
|
location /t {
|
|
content_by_lua '
|
|
local function f()
|
|
ngx.log(ngx.ERR, "Bad bad bad")
|
|
end
|
|
ngx.timer.at(0, f)
|
|
ngx.sleep(0.001)
|
|
ngx.say("ok")
|
|
';
|
|
}
|
|
--- log_level: error
|
|
--- error_log_file: syslog:server=127.0.0.1:12345
|
|
--- udp_listen: 12345
|
|
--- udp_query eval: qr/Bad bad bad/
|
|
--- udp_reply: hello
|
|
--- wait: 0.1
|
|
--- request
|
|
GET /t
|
|
--- response_body
|
|
ok
|
|
--- error_log
|
|
Bad bad bad
|
|
--- skip_nginx: 4: < 1.7.1
|
|
|