diff --git a/src/lua/bsdsocket.lua b/src/lua/bsdsocket.lua index e7aa926cda7ada49175a24c5132020c859babdab..3259a5921bc5240b4586afa749e5b2e19e9d2a5b 100644 --- a/src/lua/bsdsocket.lua +++ b/src/lua/bsdsocket.lua @@ -6,6 +6,8 @@ local ffi = require('ffi') local boxerrno = require('errno') local internal = require('socket') local fiber = require('fiber') +local fio = require('fio') +local log = require('log') ffi.cdef[[ struct socket { @@ -980,7 +982,7 @@ local function tcp_server_loop(server, s, addr) fiber.create(tcp_server_handler, server, sc, from) end if addr.family == 'AF_UNIX' and addr.port then - os.remove(addr.port) -- remove unix socket + fio.unlink(addr.port) -- remove unix socket end end @@ -988,6 +990,43 @@ local function tcp_server_usage() error('Usage: socket.tcp_server(host, port, handler | opts)') end +local function tcp_server_bind(s, addr) + if s:bind(addr.host, addr.port) then + return true + end + + if addr.family ~= 'AF_UNIX' then + return false + end + + if boxerrno() ~= boxerrno.EADDRINUSE then + return false + end + + local save_errno = boxerrno() + + local sc = tcp_connect(addr.host, addr.port) + if sc ~= nil then + sc:close() + boxerrno(save_errno) + return false + end + + if boxerrno() ~= boxerrno.ECONNREFUSED then + boxerrno(save_errno) + return false + end + + log.info("tcp_server: remove dead UNIX socket: %s", addr.port) + if not fio.unlink(addr.port) then + log.warn("tcp_server: %s", boxerrno.strerror()) + boxerrno(save_errno) + return false + end + return s:bind(addr.host, addr.port) +end + + local function tcp_server(host, port, opts, timeout) local server = {} if type(opts) == 'function' then @@ -1025,7 +1064,7 @@ local function tcp_server(host, port, opts, timeout) else s:setsockopt('SOL_SOCKET', 'SO_REUSEADDR', 1) -- ignore error end - if not s:bind(addr.host, addr.port) or not s:listen(backlog) then + if not tcp_server_bind(s, addr) or not s:listen(backlog) then local save_errno = boxerrno() s:close() boxerrno(save_errno) diff --git a/src/lua/init.cc b/src/lua/init.cc index 02ca2146cb47f870ab66c5b64c5115acda175cda..02fa51d7e6f357c9db52882451932aa0264b0a3b 100644 --- a/src/lua/init.cc +++ b/src/lua/init.cc @@ -94,11 +94,11 @@ static const char *lua_modules[] = { "uuid", uuid_lua, "log", log_lua, "uri", uri_lua, + "fio", fio_lua, "socket", bsdsocket_lua, "net.box", box_net_box_lua, "console", console_lua, "tap", tap_lua, - "fio", fio_lua, "help.en_US", help_en_US_lua, "help", help_lua, NULL @@ -293,9 +293,9 @@ tarantool_lua_init(const char *tarantool_bin, int argc, char **argv) tarantool_lua_fiber_init(L); tarantool_lua_ipc_init(L); tarantool_lua_errno_init(L); + tarantool_lua_fio_init(L); tarantool_lua_bsdsocket_init(L); tarantool_lua_pickle_init(L); - tarantool_lua_fio_init(L); luaopen_msgpack(L); lua_pop(L, 1); luaopen_yaml(L); diff --git a/test/box/bsdsocket.result b/test/box/bsdsocket.result index 043ac1e95ce91274c569ca22e00fb7a3f63a7a39..e59baf99d259b3e51bfd1b508028aa22a7d525d2 100644 --- a/test/box/bsdsocket.result +++ b/test/box/bsdsocket.result @@ -279,7 +279,7 @@ s:getsockopt('SOL_SOCKET', 'SO_DEBUG') ... s:setsockopt('SOL_SOCKET', 'SO_ACCEPTCONN', 1) --- -- error: 'builtin/socket.lua:341: Socket option SO_ACCEPTCONN is read only' +- error: 'builtin/socket.lua:343: Socket option SO_ACCEPTCONN is read only' ... s:getsockopt('SOL_SOCKET', 'SO_RCVBUF') > 32 --- @@ -1433,3 +1433,45 @@ yaml.decode(yaml.encode(s)).fd == s:fd() s = nil --- ... +-- start AF_UNIX server with dead socket exists +path = '/tmp/tarantool-test-socket' +--- +... +s = socket('AF_UNIX', 'SOCK_STREAM', 0) +--- +... +s:bind('unix/', path) +--- +- true +... +s:close() +--- +- true +... +s = socket('AF_UNIX', 'SOCK_STREAM', 0) +--- +... +{ s:bind('unix/', path), errno.strerror() } +--- +- - false + - Address already in use +... +s:close() +--- +- true +... +s = socket.tcp_server('unix/', path, function() end) +--- +... +s ~= nil +--- +- true +... +s:close() +--- +- true +... +fio.stat(path) == nil +--- +- true +... diff --git a/test/box/bsdsocket.test.lua b/test/box/bsdsocket.test.lua index faf0346c4099676777570ff8f70f3c88caa69d16..9081ad5a352d20d485bb9013481f03448d9476e1 100644 --- a/test/box/bsdsocket.test.lua +++ b/test/box/bsdsocket.test.lua @@ -482,3 +482,18 @@ s.waiters json.decode(json.encode(s)).fd == s:fd() yaml.decode(yaml.encode(s)).fd == s:fd() s = nil + +-- start AF_UNIX server with dead socket exists +path = '/tmp/tarantool-test-socket' +s = socket('AF_UNIX', 'SOCK_STREAM', 0) +s:bind('unix/', path) +s:close() + +s = socket('AF_UNIX', 'SOCK_STREAM', 0) +{ s:bind('unix/', path), errno.strerror() } +s:close() + +s = socket.tcp_server('unix/', path, function() end) +s ~= nil +s:close() +fio.stat(path) == nil