Skip to content

Commit

Permalink
fix(autoclose) only auto-close accepted connections
Browse files Browse the repository at this point in the history
Only if a connection originates from accepting a connection request
on a server socket it will be auto-closed.
  • Loading branch information
Tieske committed Jul 29, 2022
1 parent 25c4d51 commit eab7120
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 5 deletions.
10 changes: 8 additions & 2 deletions docs/index.html
Expand Up @@ -103,8 +103,14 @@ <h2><a name="history"></a>History</h2>
<dt><strong>Copas x.x.x</strong> [unreleased]</dt>
<dd><ul>
<li>Fixed: yielding to the Copas scheduler from user-code now throws a proper error and
no longer breaks the loop. Breaking the loop could also happen if a thread terminated with
at leaast 2 return values.</li>
no longer breaks the loop. Breaking the loop could also happen if a thread returned with
at least 2 return values.</li>
<li>Fixed: wrongly auto-closing sockets. Upon exiting a coroutine, sockets would be automatically
closed. This should only be the case for accepted TCP connections on a TCP server socket. This caused issues
for sockets shared between threads.<br />
[breaking]: this changes behavior, auto-close is now determined when accepting the connection, and no longer when
terminating the handler thread. This will only affect users that dynamically change <code>copas.autoclose</code>
at runtime.</li>
<li>Added: added <code>sempahore:destroy()</code></li>
<li>Added: <code>copas.settimeouts</code>, to set separate timeouts for connect, send, receive</li>
<li>Added: queue class, see module "copas.queue"</li>
Expand Down
3 changes: 2 additions & 1 deletion docs/reference.html
Expand Up @@ -157,7 +157,8 @@ <h3>Copas dispatcher main functions</h3>
</dd>

<dt><strong><code>copas.autoclose</code></strong></dt>
<dd>Constant that controls whether sockets are automatically closed.<br />
<dd>Constant that controls whether sockets are automatically closed. This only applies
to incoming connections accepted on a TCP server socket.<br />
When a TCP handler function completes and terminates, then the client
socket will be automatically closed when <code>copas.autoclose</code> is
truthy.
Expand Down
25 changes: 23 additions & 2 deletions src/copas.lua
Expand Up @@ -267,6 +267,9 @@ end -- _sleeping
local _servers = newsocketset() -- servers being handled
local _threads = setmetatable({}, {__mode = "k"}) -- registered threads added with addthread()
local _canceled = setmetatable({}, {__mode = "k"}) -- threads that are canceled and pending removal
local _autoclose = setmetatable({}, {__mode = "kv"}) -- sockets (value) to close when a thread (key) exits
local _autoclose_r = setmetatable({}, {__mode = "kv"}) -- reverse: sockets (key) to close when a thread (value) exits


-- for each socket we log the last read and last write times to enable the
-- watchdog to follow up if it takes too long.
Expand Down Expand Up @@ -681,6 +684,14 @@ local function ssl_wrap(skt, wrap_params)
copas.settimeouts(nskt, user_timeouts_connect[skt],
user_timeouts_send[skt], user_timeouts_receive[skt]) -- copy copas user-timeout to newly wrapped one

local co = _autoclose_r[skt]
if co then
-- socket registered for autoclose, move registration to wrapped one
_autoclose[co] = nskt
_autoclose_r[skt] = nil
_autoclose_r[nskt] = co
end

local sock_name = object_names[skt]
if sock_name ~= tostring(skt) then
-- socket had a custom name, so copy it over
Expand Down Expand Up @@ -1012,9 +1023,13 @@ local function _doTick (co, skt, ...)
pcall(_errhandlers[co] or _deferror, res, co, skt)
end

if skt and copas.autoclose and isTCP(skt) then
skt:close() -- do not auto-close UDP sockets, as the handler socket is also the server socket
local skt_to_close = _autoclose[co]
if skt_to_close then
skt_to_close:close()
_autoclose[co] = nil
_autoclose_r[skt_to_close] = nil
end

_errhandlers[co] = nil
end

Expand All @@ -1036,6 +1051,12 @@ local _accept do

local co = coroutine_create(handler)
object_names[co] = object_names[server_skt] .. ":handler_" .. count

if copas.autoclose then
_autoclose[co] = client_skt
_autoclose_r[client_skt] = co
end

_doTick(co, client_skt)
end
end
Expand Down

0 comments on commit eab7120

Please sign in to comment.