diff --git a/Makefile b/Makefile
index 8b2f39b..bbb7277 100644
--- a/Makefile
+++ b/Makefile
@@ -60,6 +60,7 @@ test: certs
$(LUA) $(DELIM) $(PKGPATH) tests/starve.lua
$(LUA) $(DELIM) $(PKGPATH) tests/tcptimeout.lua
$(LUA) $(DELIM) $(PKGPATH) tests/timer.lua
+ $(LUA) $(DELIM) $(PKGPATH) tests/timeout_errors.lua
$(LUA) $(DELIM) $(PKGPATH) tests/tls-sni.lua
$(LUA) $(DELIM) $(PKGPATH) tests/udptimeout.lua
$(LUA) $(DELIM)
diff --git a/docs/index.html b/docs/index.html
index cb217cc..57865e6 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -100,6 +100,13 @@
Dependencies
History
+ - Copas 4.3.x [unreleased]
+
+ - Fix: error handler for timeouts. Underlying
+ bug is in coxpcall, and hence this only applies to PuC Lua 5.1.
+
+
+
- Copas 4.3.1 [21/Sep/2022]
- Fix: with Lua 5.1 the timeouts would resume the wrapped (by coxpcall)
diff --git a/src/copas.lua b/src/copas.lua
index f072c96..a7863c7 100644
--- a/src/copas.lua
+++ b/src/copas.lua
@@ -1236,13 +1236,16 @@ end
do
local timeout_register = setmetatable({}, { __mode = "k" })
+ local time_out_thread
local timerwheel = require("timerwheel").new({
precision = TIMEOUT_PRECISION, -- timeout precision 100ms
ringsize = math.floor(60/TIMEOUT_PRECISION), -- ring size 1 minute
- err_handler = function(...) return _deferror(...) end,
+ err_handler = function(err)
+ return _deferror(err, time_out_thread)
+ end,
})
- copas.addnamedthread("copas_core_timer", function()
+ time_out_thread = copas.addnamedthread("copas_core_timer", function()
while true do
copas.sleep(TIMEOUT_PRECISION)
timerwheel:step()
diff --git a/tests/errhandlers.lua b/tests/errhandlers.lua
index f55736d..25755d0 100644
--- a/tests/errhandlers.lua
+++ b/tests/errhandlers.lua
@@ -68,7 +68,7 @@ if _VERSION ~= "Lua 5.1" then
print = old_print --luacheck: ignore
- assert(msg:find("errhandlers%.lua:%d-: hi there! %(coroutine: nil, socket: nil%)"), "got:\n"..msg)
+ assert(msg:find("errhandlers%.lua:%d-: hi there! %(coroutine: copas_core_timer, socket: nil%)"), "got:\n"..msg)
assert(msg:find("stack traceback:.+errhandlers%.lua"), "got:\n"..msg)
end
end
diff --git a/tests/timeout_errors.lua b/tests/timeout_errors.lua
new file mode 100644
index 0000000..70f2b98
--- /dev/null
+++ b/tests/timeout_errors.lua
@@ -0,0 +1,50 @@
+-- Tests Copas timeout mnechanism, when a timeout handler errors out
+--
+-- Run the test file, it should exit successfully without hanging.
+
+-- make sure we are pointing to the local copas first
+package.path = string.format("../src/?.lua;%s", package.path)
+local copas = require("copas")
+
+
+local tests = {}
+
+
+function tests.error_on_timeout()
+ local err_received
+
+ copas.addthread(function()
+ copas.setErrorHandler(function(err, coro, skt)
+ err_received = err
+ end, true)
+ print "setting timeout in 0.1 seconds"
+ copas.timeout(0.1, function()
+ print "throwing an error now..."
+ error("oops...")
+ end)
+ print "going to sleep for 1 second"
+ copas.sleep(1)
+
+ if not (err_received or ""):find("oops...", 1, true) then
+ print("expected to find the error string 'oops...', but got: " .. tostring(err_received))
+ os.exit(1)
+ end
+ end)
+
+ copas.loop()
+end
+
+
+
+
+
+-- test "framework"
+for name, test in pairs(tests) do
+ print("testing: "..tostring(name))
+ local status, err = pcall(test)
+ if not status then
+ error(err)
+ end
+end
+
+print("[✓] all tests completed successuly")