From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id DA8436EC44; Mon, 9 Nov 2026 01:01:06 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org DA8436EC44 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1794175267; bh=1/EUPXSVCkm8OoG+gCL8NXRvPOGos0w9AV6n+1Un78I=; h=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=DK9QBCUQEo25ezn81jSVEOlQ9Xg0V+htpwBEnVTljJe6SNks2OmVX3AaX4K5c58tF zz2fKXeCFnzE9UkN9tFWy0uK4GD07SwqFCrOEXEqyd9UDTQxPtT8mgbGXElkOoq4/G 76AnwXD3IF1FfFZxnUfN8Q4W+cYemYvMmls8rras= Received: from send35.i.mail.ru (send35.i.mail.ru [89.221.237.130]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 3A5936EC44 for ; Mon, 9 Nov 2026 01:01:05 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 3A5936EC44 Received: by exim-smtp-5cc8b577fd-b8srs with esmtpa (envelope-from ) id 1xQAwc-00000000A1J-2onn; Mon, 09 Nov 2026 01:00:59 +0300 Message-ID: <5023608f-2000-453d-82c2-d44ede3e5794@tarantool.org> Date: Mon, 9 Nov 2026 01:00:58 +0300 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird To: Sergey Kaplun References: <68d8da9f72cbf7237b0e21f9c643789d36fa82a8.1793574664.git.e.temirgaleev@tarantool.org> Content-Language: en-US In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Mailru-Src: smtp X-4EC0790: 10 X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD96F2D5E088614A2372B8D188DC4D6F5CA9E1B962CF22E6E0E182A05F5380850407545E3A5B6B769853DE06ABAFEAF6705969EC595C588AADC144EB2C858EDA76149B610CA6D60D10F X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7B9D6DADD6B53929DEA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637AC83A81C8FD4AD23D82A6BABE6F325AC2E85FA5F3EDFCBAA7353EFBB553375669BFFA6ABF9D5DBB93A6B4CB57BD4373D98B461B7B547345D0793A8D5F6D8A82F389733CBF5DBD5E9D5E8D9A59859A8B636DA1BED736F9328CC7F00164DA146DA6F5DAA56C3B73B237318B6A418E8EAB8090A508E0FED6299176DF2183F8FC7C031128297CE6726AFCD04E86FAF290E2DB606B96278B59C421DD303D21008E29813377AFFFEAFD269A417C69337E82CC2E827F84554CEF50127C277FBC8AE2E8BA83251EDC214901ED5E8D9A59859A8B69E1F1F50303427A9089D37D7C0E48F6C5571747095F342E88FB05168BE4CE3AF X-C1DE0DAB: 0D63561A33F958A50A300E66BCF5318C5002B1117B3ED696117C684EB3C47CEA54BB1175C6E7DD94823CB91A9FED034534781492E4B8EEAD220496FFA5CD4785BDAD6C7F3747799A X-C8649E89: 1C3962B70DF3F0AD73CAD6646DEDE1918E10F71CB4DF9F96AB70F9BE574AE9C625B6776AC983F447FC0B9F89525902EE6F57B2FD27647F25E66C117BDB76D6595D4C2D0D9733AED94AD324E185083A6F7036D3555A1FF086FF376897FA53699D0B202649D0CFD24FB8341EE9D5BE9A0ABC3A65A2BB3B95C7DBFE054AC7D2BB556274C0CF758D1AD6C7CEAA0681F5848F4C41F94D744909CEEF9E35A692215F79327F81E6EEE0AEB67A0F9F91F029B6AF33F2C28C22F508233FCF178C6DD14203 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu53w8ahmwBjZKM/YPHZyZHvz5uv+WouB9+ObcCpyrx6l7KImUglyhkEat/+ysWwi0gdhEs0JGjl6ggRWTy1haxBpVdbIX1nthFXOcIETfglQORZ0zpDET4Zrk3igikrdHlWIxvGSdJQo7eOphDQ8QPJMA= X-Mailru-Sender: 015BA6FC0EFA223A63A6570A1A0312859146D76A925A7406B951B70A5BD4BD8E233DAA8ED6646D0F3F8606E94880FE02E62B12C1FE0372A178274A4A9E9E44FD2A114EDA040D8818F01FF9DF31C397A372D6B4FCE48DF648AE208404248635DF X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCH luajit v3 2/2] Improve CLI signal handling on POSIX. X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Evgeniy Temirgaleev via Tarantool-patches Reply-To: Evgeniy Temirgaleev Cc: tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" Sergey, thanks for review! Please, see my answers below. Fixes are force pushed to the branch. On 11/3/26 3:14 PM, Sergey Kaplun wrote: > Envgeniy, > Thanks for the patch! > LGTM, with minor nits below. > > On 02.11.26, Evgeniy Temirgaleev wrote: >> From: Mike Pall >> >> (cherry picked from commit 423ac2144b0447c925596f4d93e073ce501ed4e1) >> >> An obsolete signal() function in glibc is implemented as a wrapper for >> POSIX sigaction() call with BSD semantic. In particular, it provides > > Typo: s/semantic/semantics/ > Fixed. >> an SA_RESTART flag for SIGINT handler [1-2]. The latter makes certain >> system calls, e.g. read() or wait(), restartable across signals [3]. >> >> The patch switches from signal() to sigaction() for POSIX systems >> to obtain an explicit control of the signal flag set, which must >> not contain SA_RESTART flag. (Actually, the empty flag set is >> used.) >> >> 1. https://man7.org/linux/man-pages/man2/signal.2.html >> 2. https://ftp.gnu.org/gnu/glibc/glibc-2.44.tar.xz (sysdeps/posix/signal.c, line 44) >> 3. https://man7.org/linux/man-pages/man2/sigaction.2.html >> >> Temir Galeev: >> * added the description and the test for the problem >> >> Part of tarantool/tarantool#13442 >> --- >> src/luajit.c | 23 +++++-- >> ...ket-fix-cli-posix-sigint-handling.test.lua | 64 +++++++++++++++++++ >> .../script.lua | 26 ++++++++ >> 3 files changed, 109 insertions(+), 4 deletions(-) >> create mode 100644 test/tarantool-tests/lj-noticket-fix-cli-posix-sigint-handling.test.lua >> create mode 100644 test/tarantool-tests/lj-noticket-fix-cli-posix-sigint-handling/script.lua >> >> diff --git a/src/luajit.c b/src/luajit.c >> index d9d85361..d35bea54 100644 >> --- a/src/luajit.c >> +++ b/src/luajit.c > > > >> diff --git a/test/tarantool-tests/lj-noticket-fix-cli-posix-sigint-handling.test.lua b/test/tarantool-tests/lj-noticket-fix-cli-posix-sigint-handling.test.lua >> new file mode 100644 >> index 00000000..5b235660 >> --- /dev/null >> +++ b/test/tarantool-tests/lj-noticket-fix-cli-posix-sigint-handling.test.lua >> @@ -0,0 +1,64 @@ >> +local tap = require('tap') >> + >> +-- The test checks that luajit CLI stop hook is executed on > > Typo: s/luajit/the LuaJIT/ > Fixed >> +-- SIGINT on a blocking system call (read(), waitpid(), etc.). >> +-- >> +-- The test runs luajit CLI with a script, which prints it's PID > > Typo: s/luajit/the LuaJIT/ > Typo: s/it's/its/ > Fixed >> +-- as a ready marker and blocks on a read() call. After the >> +-- child's PID number is read from child's pipe, the test send > > Typo: s/child's/the child's/ > Typo: s/send/sends/ > Fixed >> +-- SIGINT to the child. >> +-- With a patch applied (no SA_RESTART flag for SIGINT handler) >> +-- read() call is interrupted and the CLI's Lua stop hook >> +-- executed. > > Typo: s/executed/is executed/ > Fixed >> +-- Without a patch (SA_RESTART flag is present for SIGINT >> +-- handler) read() call is restarted, the test and the child is > > Typo: s/is blocked/are blocked/ > Fixed >> +-- blocked on a pipe read until the child is terminated by >> +-- SIGALRM. The test reads nothing from the child and fails. >> + >> +local test = tap.test('lj-noticket-fix-cli-posix-sigint-handling'):skipcond({ >> + -- The patched code is not present in Tarantool binary: >> + ["Disabled due to Tarantool uses it's own signal handling"] = _TARANTOOL, > > Nit: s/"/'/g > Here is a single quite inside a string. >> + ['Disabled on POSIX nonconformant OS'] = jit.os ~= 'BSD' and >> + jit.os ~= 'Linux' and >> + jit.os ~= 'OSX' and >> + jit.os ~= 'POSIX', >> +}) >> + >> +local ffi = require('ffi') >> +ffi.cdef[[ >> + int kill(int pid, int sig); >> +]] >> +local SIGINT = 2 >> + >> +test:plan(1) >> +local utils = require('utils') >> +local script = utils.exec.test_data(arg, 'script.lua') >> +local cmd = ('exec %s %s 2>&1'):format(utils.exec.luacmd(arg), script) >> +local proc = io.popen(cmd) >> + >> +local MARKER = 'CHILD_PID:' >> +local RMARKER = '^'..MARKER..'(%d+)$' > > Typo: s/../ .. /g > Fixed. >> +-- The child prints its PID after the CLI has installed the SIGINT >> +-- handler, so it is a readiness marker. Skip possible noise >> +-- lines, collect pre-marker output for error reporting. >> +local lines_for_diag = {'child output:'} >> +local pid, line >> +repeat >> + line = proc:read('*l') >> + if line ~= nil then >> + table.insert(lines_for_diag, line) >> + local match = line:match(RMARKER) >> + if match ~= nil then pid = tonumber(match) end >> + end >> +until line == nil or pid ~= nil >> +if pid == nil then >> + test:diag(table.concat(lines_for_diag, '\n')) >> +end >> +assert(pid ~= nil, 'the child process must report its PID') >> + >> +local res = ffi.C.kill(pid, SIGINT) >> +assert(res == 0, 'SIGINT delivery failed') >> +local output = proc:read('*a') >> +proc:close() >> +test:like(output, 'interrupted!', 'SIGINT interrupts the blocking call') >> +test:done(true) >> diff --git a/test/tarantool-tests/lj-noticket-fix-cli-posix-sigint-handling/script.lua b/test/tarantool-tests/lj-noticket-fix-cli-posix-sigint-handling/script.lua >> new file mode 100644 >> index 00000000..d2430a52 >> --- /dev/null >> +++ b/test/tarantool-tests/lj-noticket-fix-cli-posix-sigint-handling/script.lua >> @@ -0,0 +1,26 @@ >> +local ffi = require('ffi') >> + >> +ffi.cdef[[ >> + int pipe(int *fds); >> + int getpid(void); >> + long read(int fd, void *buf, size_t count); >> + unsigned int alarm(unsigned int seconds); >> +]] >> + >> +local fds = ffi.new('int[2]') >> +assert(ffi.C.pipe(fds) == 0) >> + >> +-- Fail instead of hanging forever if SIGINT does not break >> +-- the call. (SIGALRM isn't handled by CLI.) >> +ffi.C.alarm(10) >> + >> +-- The CLI installs the SIGINT handler before the script >> +-- starts, so this line is the readiness marker for the test. >> +local MARKER = 'CHILD_PID:' >> +io.write(MARKER, ffi.C.getpid(), '\n') >> +io.flush() >> + >> +-- Block in read(2) until SIGINT. Without SA_RESTART it returns >> +-- EINTR and the CLI runs the Lua hook, which raises >> +-- "interrupted!". >> +ffi.C.read(fds[0], ffi.new('char[1]'), 1) > > Why don't use `io.read()` here? Same semantics but additional > correlation with the comment in sources. > `io.read()` may not block in non console environment. Added a comment. >> -- >> 2.49.0 >> > --- Commit msg: ... An obsolete signal() function in glibc is implemented as a wrapper for POSIX sigaction() call with BSD semantics. In particular, it provides an SA_RESTART flag for SIGINT handler [1-2]. The latter makes certain system calls, e.g. read() or wait(), restartable across signals [3]. ... --- diff --git a/test/tarantool-tests/lj-noticket-fix-cli-posix-sigint-handling.test.lua b/test/tarantool-tests/lj-noticket-fix-cli-posix-sigint-handling.test.lua index 5b235660..e080b7f3 100644 --- a/test/tarantool-tests/lj-noticket-fix-cli-posix-sigint-handling.test.lua +++ b/test/tarantool-tests/lj-noticket-fix-cli-posix-sigint-handling.test.lua @@ -1,17 +1,17 @@ local tap = require('tap') --- The test checks that luajit CLI stop hook is executed on +-- The test checks that LuaJIT CLI stop hook is executed on -- SIGINT on a blocking system call (read(), waitpid(), etc.). -- --- The test runs luajit CLI with a script, which prints it's PID +-- The test runs LuaJIT CLI with a script, which prints its PID -- as a ready marker and blocks on a read() call. After the --- child's PID number is read from child's pipe, the test send --- SIGINT to the child. +-- the child's PID number is read from child's pipe, the test +-- sends SIGINT to the child. -- With a patch applied (no SA_RESTART flag for SIGINT handler) -- read() call is interrupted and the CLI's Lua stop hook --- executed. +-- is executed. -- Without a patch (SA_RESTART flag is present for SIGINT --- handler) read() call is restarted, the test and the child is +-- handler) read() call is restarted, the test and the child are -- blocked on a pipe read until the child is terminated by -- SIGALRM. The test reads nothing from the child and fails. @@ -37,7 +37,7 @@ local cmd = ('exec %s %s 2>&1'):format(utils.exec.luacmd(arg), script) local proc = io.popen(cmd) local MARKER = 'CHILD_PID:' -local RMARKER = '^'..MARKER..'(%d+)$' +local RMARKER = '^' .. MARKER .. '(%d+)$' -- The child prints its PID after the CLI has installed the SIGINT -- handler, so it is a readiness marker. Skip possible noise -- lines, collect pre-marker output for error reporting. diff --git a/test/tarantool-tests/lj-noticket-fix-cli-posix-sigint-handling/script.lua b/test/tarantool-tests/lj-noticket-fix-cli-posix-sigint-handling/script.lua index d2430a52..fab558e7 100644 --- a/test/tarantool-tests/lj-noticket-fix-cli-posix-sigint-handling/script.lua +++ b/test/tarantool-tests/lj-noticket-fix-cli-posix-sigint-handling/script.lua @@ -1,15 +1,10 @@ local ffi = require('ffi') ffi.cdef[[ int pipe(int *fds); int getpid(void); long read(int fd, void *buf, size_t count); unsigned int alarm(unsigned int seconds); ]] + +-- The script runs via 'popen()' with closed pipe read-end, +-- and the stdin is not guaranteed to be connected somewhere. +-- Reading from it may result in EOF. +-- So, establish the new pipe, which read-end would block. local fds = ffi.new('int[2]') assert(ffi.C.pipe(fds) == 0) -- Fail instead of hanging forever if SIGINT does not break -- the call. (SIGALRM isn't handled by CLI.) ffi.C.alarm(10) -- -- Best regards, Evgeniy Temirgaleev