| # vim:set ft= ts=4 sw=4 et fdm=marker: |
| use lib 'lib'; |
| 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 + 76); |
| |
| #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\] \[string "content_by_lua"\]:\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", |
| ] |
| |
| |
| |
| === 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\] \[string "content_by_lua"\]:\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\] \[string "content_by_lua"\]:\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\] \[string "content_by_lua"\]:\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: nil closed", |
| ] |
| |
| |
| |
| === 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.05 |
| --- no_error_log |
| [error] |
| [alert] |
| [crit] |
| |
| --- error_log eval |
| [ |
| qr/\[lua\] \[string "content_by_lua"\]:\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\] \[string "log_by_lua"\]:\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 |
| lua sleep cleanup |
| delete timer 1000 |
| delete thread 3 |
| 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 |
| lua sleep cleanup |
| delete timer 1000 |
| delete thread 3 |
| 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 |
| lua ngx.timer expired |
| http lua close fake http connection |
| trace: [m][f][g] |
| |
| |
| |
| === 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 |
| 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\] \[string "content_by_lua"\]:\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\] \[string "content_by_lua"\]:\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 ", |
| ] |
| |