Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/ngx_http_lua_pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -2616,6 +2616,11 @@ ngx_http_lua_pipe_proc_wait_cleanup(void *data)
wait_co_ctx->cleanup = NULL;

if (proc->pipe == NULL) {
/* pipe_proc_destroy already ran (LIFO pool cleanup) and closed
* connections, but wait uses wait_co_ctx->sleep (a standalone event,
* not tied to any connection), so ngx_close_connection in
* pipe_proc_destroy cannot cancel it. Clear it here. */
ngx_http_lua_pipe_clear_event(&wait_co_ctx->sleep);
return;
}

Expand Down
28 changes: 28 additions & 0 deletions t/191-pipe-proc-quic-close-crash.t
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,31 @@ GET /t
--- curl_error eval: qr/\(28\)/
--- no_error_log
[alert]



=== TEST 2: pipe wait timer must not fire after pool is freed on QUIC connection close
--- config
location = /t {
content_by_lua_block {
local proc = require("ngx.pipe").spawn({"sleep", "100"})
-- set_timeouts(write_timeout, stdout_timeout, stderr_timeout, wait_timeout)
proc:set_timeouts(nil, nil, nil, 1000) -- 1 s wait timeout

-- This call yields and arms a 1 s timer on wait_co_ctx->sleep.
-- Unlike stdout/stderr read timers (tied to a connection),
-- the wait timer is a standalone ngx_event_t, so
-- ngx_close_connection in pipe_proc_destroy cannot cancel it.
-- Without the fix in wait_cleanup, the timer fires after pool
-- is freed → SIGSEGV in ngx_http_lua_pipe_resume_wait_handler.
proc:wait()
}
}
--- request
GET /t
--- timeout: 0.5
--- wait: 2
--- ignore_response
--- curl_error eval: qr/\(28\)/
--- no_error_log
[alert]
Loading