comparison util/adminstream.lua @ 13794:471b676e64eb 13.0

util.adminstream: Fix traceback on double-close (fixes #1913) In some circumstances, particularly with 'opportunistic_writes' and 'fatal_errors' enabled in the epoll backend, the connection may be closed halfway through the session close process (because it contains debug logging, which in the case of the watch:log() command, will trigger a write to the socket). The chosen fix is to cache session.conn in a local variable (we already did this later on, but this pulls it up to the top of the function, which is generally more correct anyway).
author Matthew Wild <mwild1@gmail.com>
date Mon, 31 Mar 2025 16:25:09 +0100
parents b1b931d5fee8
children 0afcbea41f22
comparison
equal deleted inserted replaced
13792:4ea7bd7325be 13794:471b676e64eb
80 session.log("debug", "Destroying session: %s", reason or "unknown reason"); 80 session.log("debug", "Destroying session: %s", reason or "unknown reason");
81 end 81 end
82 82
83 local function session_close(session, reason) 83 local function session_close(session, reason)
84 local log = session.log or log; 84 local log = session.log or log;
85 if session.conn then 85 local conn = session.conn;
86 if conn then
86 if session.notopen then 87 if session.notopen then
87 session:open_stream(); 88 session:open_stream();
88 end 89 end
89 if reason then -- nil == no err, initiated by us, false == initiated by client 90 if reason then -- nil == no err, initiated by us, false == initiated by client
90 local stream_error = st.stanza("stream:error"); 91 local stream_error = st.stanza("stream:error");
113 114
114 local reason_text = (reason and (reason.name or reason.text or reason.condition)) or reason; 115 local reason_text = (reason and (reason.name or reason.text or reason.condition)) or reason;
115 session.log("debug", "c2s stream for %s closed: %s", session.full_jid or session.ip or "<unknown>", reason_text or "session closed"); 116 session.log("debug", "c2s stream for %s closed: %s", session.full_jid or session.ip or "<unknown>", reason_text or "session closed");
116 117
117 -- Authenticated incoming stream may still be sending us stanzas, so wait for </stream:stream> from remote 118 -- Authenticated incoming stream may still be sending us stanzas, so wait for </stream:stream> from remote
118 local conn = session.conn;
119 if reason_text == nil and not session.notopen and session.type == "c2s" then 119 if reason_text == nil and not session.notopen and session.type == "c2s" then
120 -- Grace time to process data from authenticated cleanly-closed stream 120 -- Grace time to process data from authenticated cleanly-closed stream
121 add_task(stream_close_timeout, function () 121 add_task(stream_close_timeout, function ()
122 if not session.destroyed then 122 if not session.destroyed then
123 session.log("warn", "Failed to receive a stream close response, closing connection anyway..."); 123 session.log("warn", "Failed to receive a stream close response, closing connection anyway...");