From ca51cbe93b0ea75840d4c8157e8e9c79fac37e14 Mon Sep 17 00:00:00 2001 From: Dmitry Simonenko <pmwkaa@gmail.com> Date: Tue, 12 Mar 2013 17:43:00 +0400 Subject: [PATCH] lua-socket-race-fix: race fix in coeio_custom. Fix race between fiber_yield_timeout() and completed request during yield itself. In that case eio_poll will complete request and free its handle. eio_cancel try to cancel completed and freed request. Also, fix unpredictable result during timedout test. --- src/coeio.m | 5 ++++- test/box/socket.result | 27 ++++++++++----------------- test/box/socket.test | 20 ++++++++++---------- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/coeio.m b/src/coeio.m index 1e5947d3a1..d966d8f590 100644 --- a/src/coeio.m +++ b/src/coeio.m @@ -122,6 +122,7 @@ struct coeio_task { va_list ap; /** Callback results. */ ssize_t result; + int complete; int errorno; }; @@ -150,6 +151,7 @@ coeio_on_complete(eio_req *req) struct coeio_task *task = req->data; task->result = req->result; task->errorno = req->errorno; + task->complete = 1; fiber_wakeup(task->fiber); } return 0; @@ -188,12 +190,13 @@ coeio_custom(ssize_t (*func)(va_list ap), ev_tstamp timeout, ...) task.fiber = fiber; task.func = func; task.result = -1; + task.complete = 0; va_start(task.ap, timeout); struct eio_req *req = eio_custom(coeio_custom_cb, 0, coeio_on_complete, &task); if (req == NULL) { errno = ENOMEM; - } else if (fiber_yield_timeout(timeout)) { + } else if (fiber_yield_timeout(timeout) && !task.complete) { /* timeout. */ errno = ETIMEDOUT; task.result = -1; diff --git a/test/box/socket.result b/test/box/socket.result index 8bc0ba5fb5..befd43b982 100644 --- a/test/box/socket.result +++ b/test/box/socket.result @@ -92,17 +92,19 @@ lua s:close() lua s:close() --- ... -lua s:connect('somewhereelse', '30303', 0.01) +lua sr, se = s:connect('somewhereelse', '30303', 0.0001) --- - - nil - - timeout - - 110 - - Connection timed out ... -lua s:error() +lua sr == nil and se == 'error' or se == 'timeout' +--- + - true +... +lua e = s:error() --- - - 110 - - Connection timed out +... +lua e == -1 or e == 110 +--- + - true ... lua s:close() --- @@ -115,11 +117,6 @@ lua s:send(1) --- error: 'box.socket: socket is not initialized' ... -lua s:error() ---- - - 110 - - Connection timed out -... lua s = box.socket.tcp() --- ... @@ -155,10 +152,6 @@ lua type(error_str) --- - string ... -lua n ---- - - 163840 -... lua status --- - timeout diff --git a/test/box/socket.test b/test/box/socket.test index 49c4a5a9f1..180927a61c 100644 --- a/test/box/socket.test +++ b/test/box/socket.test @@ -54,22 +54,23 @@ exec admin "lua s:connect(123)" exec admin "lua s:close()" exec admin "lua s:close()" -exec admin "lua s:connect('somewhereelse', '30303', 0.01)" -# timedout -exec admin "lua s:error()" +exec admin "lua sr, se = s:connect('somewhereelse', '30303', 0.0001)" +exec admin "lua sr == nil and se == 'error' or se == 'timeout'" + +# timedout or hostname resolution failed +exec admin "lua e = s:error()" +exec admin "lua e == -1 or e == 110" exec admin "lua s:close()" -################## -# # +################# +# # # socket:send() # -# # -################## +# # +################# # bad args exec admin "lua s:send()" exec admin "lua s:send(1)" -# bad file descriptor -exec admin "lua s:error()" s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) @@ -87,7 +88,6 @@ exec admin "lua type(n)" exec admin "lua type(status)" exec admin "lua type(error_code)" exec admin "lua type(error_str)" -exec admin "lua n" exec admin "lua status" exec admin "lua error_code" exec admin "lua error_str" -- GitLab