Tarantool development patches archive
 help / color / mirror / Atom feed
* [Tarantool-patches] [PATCH luajit v2 0/5] Add ASan support in LuaJIT
@ 2023-07-21  8:12 Igor Munkin via Tarantool-patches
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 1/5] ci: clean up workflow for exotic builds Igor Munkin via Tarantool-patches
                   ` (5 more replies)
  0 siblings, 6 replies; 25+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2023-07-21  8:12 UTC (permalink / raw)
  To: Sergey Kaplun, Sergey Bronnikov; +Cc: tarantool-patches

This series implements the second attempt to enable ASan support back
for LuaJIT repository.

The only thing that was missing the whole time was the option per se
(and the corresponding compile flags, obviously). Anyway, when the
option has been finally added, the dedicated CI workflow has been added
too in scope of the second patch in the series. All other info can be
found in the corresponding patches.

Besided, internal LuaJIT memory allocator is not instrumented yet
unfortunately, so to find any memory faults it's better to build LuaJIT
with system provided memory allocator (i.e. run CMake configuration
phase with -DLUAJIT_USE_SYSMALLOC=ON). However, LUAJIT_USE_SYSMALLOC
cannot be enabled on x64 without GC64, since realloc usually doesn't
return addresses in the right address range. For more info, see root
CMakeLists.txt.

Surprisingly, some hidden bugs were found while testing the
aforementioned configuration.

1. The assertions in memprof initialization, checking the state of the
allocator against NULL, can fail if this allocator requires no internal
state (e.g. glibc functions for allocating dynamic memory). In fact,
when building LuaJIT with LUAJIT_USE_SYSMALLOC option enabled, NULL is
given as the second parameter to <lua_newstate> and these assertions
fail as a result. Hence, they are simply removed.

2. Before the patch all tests in tarantool-tests suite (except
<lj-603-err-snap-restore.test.lua>) terminate their execution via
<os.exit> with the status depending on the test results. However, the
second argument of <os.exit> was omitted and Lua universe was not
properly finalized as a result. This behaviour becomes a problem, when
LuaJIT is build with LUAJIT_USE_SYSMALLOC option and AddressSanitizer
support enabled, since the sanitizer starts reporting false positive
errors about the memory allocations without the corresponding memory
releases. To resolve these errors, the second parameter to each
<os.exit> call terminating the test has to be added. To avoid loss of
the aforementioned parameter in future, <test:done> helper has been
added to the TAP module. Depending on the single parameter, the new
helper either properly finalize the test being run, or simply checks all
the test assertions and raises an error if any of them fail. The latter
case is added especially to handle <lj-603-err-snap-restore.test.lua>
specifics and still check that everything works fine.


Last but not least: for all ARM64 jobs in exotic builds testing pipeline
non-GC64 configurations were disabled, since LUAJIT_ENABLE_GC64 takes no
effect for this arch (GC64 is the only option).

Issue: https://github.com/tarantool/tarantool/issues/5878
Branch: https://github.com/tarantool/luajit/tree/hackaton/gh-5878-enable-ASAN
Tarantool related changes and CI can be found in #8846[1].

v1: https://lists.tarantool.org/tarantool-patches/cover.1689195028.git.imun@tarantool.org/T/#t

Changes in v2:
  * Fixed comments as per review by Sergey B. and Sergey K
  * Enabled LUAJIT_USE_SYSMALLOC option in sanitizers-testing.yml
  * Removed two invalid assertions in memprof sources (found via
    enabling LUAJIT_USE_SYSMALLOC option)
  * Introduced test:done helper for proper test finalization (found via
    enabling both LUAJIT_USE_ASAN and LUAJIT_USE_SYSMALLOC)
  * Little maintenance of exotic builds workflow

Igor Munkin (5):
  ci: clean up workflow for exotic builds
  memprof: remove invalid assertions
  test: introduce test:done TAP helper
  build: introduce LUAJIT_USE_ASAN option
  ci: introduce testing workflow with sanitizers

 .github/actions/setup-sanitizers/README.md    | 12 +++
 .github/actions/setup-sanitizers/action.yml   | 24 +++++
 .github/workflows/exotic-builds-testing.yml   |  4 +-
 .github/workflows/sanitizers-testing.yml      | 89 +++++++++++++++++++
 CMakeLists.txt                                | 33 +++++--
 src/lj_memprof.c                              |  2 -
 .../arm64-ccall-fp-convention.test.lua        |  2 +-
 .../bc-jit-unpatching.test.lua                |  2 +-
 .../c-library-path-length.test.lua            |  2 +-
 .../fix-bit-shift-generation.test.lua         |  2 +-
 .../tarantool-tests/fix-cdata-concat.test.lua |  2 +-
 test/tarantool-tests/fix-emit-rma.test.lua    |  2 +-
 .../fix-fold-simplify-conv-sext.test.lua      |  2 +-
 .../fix-gc-setupvalue.test.lua                |  2 +-
 .../fix-slot-check-for-mm-record.test.lua     |  2 +-
 .../gh-3196-incorrect-string-length.test.lua  |  2 +-
 .../gh-4199-gc64-fuse.test.lua                |  2 +-
 .../gh-4427-ffi-sandwich.test.lua             |  2 +-
 ...gh-4476-fix-string-find-recording.test.lua |  2 +-
 ...gh-4773-tonumber-fail-on-NUL-char.test.lua |  2 +-
 .../gh-5813-resolving-of-c-symbols.test.lua   |  2 +-
 .../gh-6065-jit-library-smoke-tests.test.lua  |  2 +-
 ...-missed-carg1-in-bctsetr-fallback.test.lua |  2 +-
 ...-6096-external-unwinding-on-arm64.test.lua |  2 +-
 ...8-fix-side-exit-patching-on-arm64.test.lua |  2 +-
 test/tarantool-tests/gh-6163-min-max.test.lua |  2 +-
 test/tarantool-tests/gh-6189-cur_L.test.lua   |  2 +-
 ...ytecode-allocator-for-comparisons.test.lua |  2 +-
 .../gh-6371-string-char-no-arg.test.lua       |  2 +-
 ...6782-stitching-in-vmevent-handler.test.lua |  2 +-
 .../gh-6976-narrowing-of-unary-minus.test.lua |  2 +-
 ...4-add-proto-trace-sysprof-default.test.lua |  2 +-
 .../gh-7745-oom-on-trace.test.lua             |  2 +-
 .../lj-350-sload-typecheck.test.lua           |  2 +-
 .../lj-351-print-tostring-number.test.lua     |  2 +-
 .../lj-356-ir-khash-non-string-obj.test.lua   |  2 +-
 .../lj-357-arm64-hrefk.test.lua               |  2 +-
 .../lj-366-strtab-correct-size.test.lua       |  2 +-
 .../lj-375-ir-bufput-signed-char.test.lua     |  2 +-
 .../lj-378-string-format-c-null-char.test.lua |  2 +-
 .../lj-408-tonumber-cdata-record.test.lua     |  2 +-
 .../lj-416-xor-before-jcc.test.lua            |  2 +-
 .../lj-418-assert-any-type.test.lua           |  2 +-
 ...6-arm64-incorrect-check-closed-uv.test.lua |  2 +-
 .../lj-430-maxirconst.test.lua                |  2 +-
 ...-arm64-constant-rematerialization.test.lua |  2 +-
 ...-445-fix-memory-probing-allocator.test.lua |  2 +-
 .../lj-463-os-date-oom.test.lua               |  2 +-
 .../lj-494-table-chain-infinite-loop.test.lua |  2 +-
 ...lj-505-fold-no-strref-for-ptrdiff.test.lua |  2 +-
 .../lj-512-profiler-hook-finalizers.test.lua  |  2 +-
 .../lj-524-fold-conv-respect-src-irt.test.lua |  2 +-
 .../lj-528-tonumber-0.test.lua                |  2 +-
 .../lj-556-fix-loop-realignment.test.lua      |  2 +-
 .../lj-574-overflow-unpack.test.lua           |  2 +-
 ...j-584-bad-renames-for-sunk-values.test.lua |  2 +-
 .../lj-586-debug-non-string-error.test.lua    |  2 +-
 .../lj-601-fix-gc-finderrfunc.test.lua        |  2 +-
 .../lj-603-err-snap-restore.test.lua          | 15 ++--
 .../lj-671-arm64-assert-after-mremap.test.lua |  2 +-
 ...lj-672-cdata-allocation-recording.test.lua |  2 +-
 .../lj-688-snap-ir-rename.test.lua            |  2 +-
 .../lj-695-ffi-vararg-call.test.lua           |  2 +-
 .../lj-698-arm-pcall-panic.test.lua           |  2 +-
 .../lj-704-bc-varg-use-def.test.lua           |  2 +-
 .../lj-726-profile-flush-close.test.lua       |  2 +-
 .../lj-727-lightuserdata-itern.test.lua       |  2 +-
 .../lj-735-io-close-on-closed-file.test.lua   |  2 +-
 .../lj-762-pcall-no-arg.test.lua              |  2 +-
 .../lj-819-fix-missing-uclo.test.lua          |  2 +-
 .../lj-864-varg-rec-base-offset.test.lua      |  2 +-
 .../lj-906-fix-err-mem.test.lua               |  2 +-
 .../tarantool-tests/lj-981-folding-0.test.lua |  2 +-
 ...instable-types-during-loop-unroll.test.lua |  2 +-
 .../lj-flush-on-trace.test.lua                |  2 +-
 test/tarantool-tests/math-modf.test.lua       |  2 +
 .../misclib-getmetrics-lapi.test.lua          |  2 +-
 .../misclib-memprof-lapi.test.lua             |  2 +-
 .../misclib-sysprof-lapi.test.lua             |  2 +-
 .../or-144-gc64-asmref-l.test.lua             |  2 +-
 .../or-232-unsink-64-kptr.test.lua            |  2 +-
 .../or-94-arm64-ir-ahuvload-bool.test.lua     |  2 +-
 test/tarantool-tests/tap.lua                  | 14 ++-
 ...onumber-negative-non-decimal-base.test.lua |  2 +-
 test/tarantool-tests/tools-utils-avl.test.lua |  2 +-
 test/tarantool-tests/unit-jit-parse.test.lua  |  2 +-
 86 files changed, 252 insertions(+), 97 deletions(-)
 create mode 100644 .github/actions/setup-sanitizers/README.md
 create mode 100644 .github/actions/setup-sanitizers/action.yml
 create mode 100644 .github/workflows/sanitizers-testing.yml

[1]: https://github.com/tarantool/tarantool/pull/8846

-- 
2.30.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Tarantool-patches] [PATCH luajit v2 1/5] ci: clean up workflow for exotic builds
  2023-07-21  8:12 [Tarantool-patches] [PATCH luajit v2 0/5] Add ASan support in LuaJIT Igor Munkin via Tarantool-patches
@ 2023-07-21  8:12 ` Igor Munkin via Tarantool-patches
  2023-07-24 10:36   ` Sergey Bronnikov via Tarantool-patches
  2023-07-26  9:37   ` Sergey Kaplun via Tarantool-patches
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 2/5] memprof: remove invalid assertions Igor Munkin via Tarantool-patches
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 25+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2023-07-21  8:12 UTC (permalink / raw)
  To: Sergey Kaplun, Sergey Bronnikov; +Cc: tarantool-patches

Unfortunately, the same mistake, that was introduced in the very first
commit f877b7691d9eae73d64c63ee3770089569915459 ("ci: introduce GitHub
Actions") and was fixed in the main testing pipeline in scope of the
commit 524616a35c1267cb9ca260b8456b71dde1881e22 ("ci: remove GC64 matrix
entries for ARM64 workflows"), was made in the new CI pipeline added in
scope of the commit 32ac0cadcba58cd69058084c88100fdcc7b7dccf ("ci: add
ARM64 architecture to exotic testing").

Specifically, CMake option LUAJIT_ENABLE_GC64 changes nothing for ARM64
LuaJIT builds (i.e. LJ_GC64 is defined on ARM64 platforms despite the
value of LUAJIT_ENABLE_GC64). As a result GC64 entry is removed from
all ARM64 flavors in exotic builds testing routine.

Besides, all flavor labels are sorted alphabetically.

Signed-off-by: Igor Munkin <imun@tarantool.org>
---
 .github/workflows/exotic-builds-testing.yml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/exotic-builds-testing.yml b/.github/workflows/exotic-builds-testing.yml
index 318fb4dd..7c57d238 100644
--- a/.github/workflows/exotic-builds-testing.yml
+++ b/.github/workflows/exotic-builds-testing.yml
@@ -34,7 +34,7 @@ jobs:
         BUILDTYPE: [Debug, Release]
         ARCH: [ARM64, x86_64]
         GC64: [ON, OFF]
-        FLAVOR: [dualnum, checkhook, nojit, gdbjit]
+        FLAVOR: [checkhook, dualnum, gdbjit, nojit]
         include:
           - BUILDTYPE: Debug
             CMAKEFLAGS: -DCMAKE_BUILD_TYPE=Debug -DLUA_USE_ASSERT=ON -DLUA_USE_APICHECK=ON
@@ -49,6 +49,8 @@ jobs:
           - FLAVOR: gdbjit
             FLAVORFLAGS: -DLUAJIT_USE_GDBJIT=ON
         exclude:
+          - ARCH: ARM64
+            GC64: OFF
           # DUALNUM is default for ARM64, no need for additional testing.
           - FLAVOR: dualnum
             ARCH: ARM64
-- 
2.30.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Tarantool-patches] [PATCH luajit v2 2/5] memprof: remove invalid assertions
  2023-07-21  8:12 [Tarantool-patches] [PATCH luajit v2 0/5] Add ASan support in LuaJIT Igor Munkin via Tarantool-patches
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 1/5] ci: clean up workflow for exotic builds Igor Munkin via Tarantool-patches
@ 2023-07-21  8:12 ` Igor Munkin via Tarantool-patches
  2023-07-24 10:46   ` Sergey Bronnikov via Tarantool-patches
  2023-07-26  9:41   ` Sergey Kaplun via Tarantool-patches
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 3/5] test: introduce test:done TAP helper Igor Munkin via Tarantool-patches
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 25+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2023-07-21  8:12 UTC (permalink / raw)
  To: Sergey Kaplun, Sergey Bronnikov; +Cc: tarantool-patches

The assertions checking the state of the allocator, being replaced by
memory profiler, against NULL can fail if this allocator requires no
internal state (e.g. glibc functions for allocating dynamic memory). In
fact, when building LuaJIT with LUAJIT_USE_SYSMALLOC option enabled,
NULL is given as the second parameter to <lua_newstate> and these
assertions fail as a result. Hence, they are simply removed.

Follows up tarantool/tarantool#5442
Needed for tarantool/tarantool#5878

Signed-off-by: Igor Munkin <imun@tarantool.org>
---
 src/lj_memprof.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/lj_memprof.c b/src/lj_memprof.c
index 8cab8204..c600c4f0 100644
--- a/src/lj_memprof.c
+++ b/src/lj_memprof.c
@@ -295,7 +295,6 @@ int lj_memprof_start(struct lua_State *L, const struct lj_memprof_options *opt)
   oalloc->allocf = lua_getallocf(L, &oalloc->state);
   lua_assert(oalloc->allocf != NULL);
   lua_assert(oalloc->allocf != memprof_allocf);
-  lua_assert(oalloc->state != NULL);
   lua_setallocf(L, memprof_allocf, oalloc->state);
 
   return PROFILE_SUCCESS;
@@ -328,7 +327,6 @@ int lj_memprof_stop(struct lua_State *L)
 
   lua_assert(memprof_allocf == lua_getallocf(L, NULL));
   lua_assert(oalloc->allocf != NULL);
-  lua_assert(oalloc->state != NULL);
   lua_setallocf(L, oalloc->allocf, oalloc->state);
 
   if (LJ_UNLIKELY(lj_wbuf_test_flag(out, STREAM_STOP))) {
-- 
2.30.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Tarantool-patches] [PATCH luajit v2 3/5] test: introduce test:done TAP helper
  2023-07-21  8:12 [Tarantool-patches] [PATCH luajit v2 0/5] Add ASan support in LuaJIT Igor Munkin via Tarantool-patches
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 1/5] ci: clean up workflow for exotic builds Igor Munkin via Tarantool-patches
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 2/5] memprof: remove invalid assertions Igor Munkin via Tarantool-patches
@ 2023-07-21  8:12 ` Igor Munkin via Tarantool-patches
  2023-07-24 10:53   ` Sergey Bronnikov via Tarantool-patches
  2023-07-26 10:43   ` Sergey Kaplun via Tarantool-patches
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 4/5] build: introduce LUAJIT_USE_ASAN option Igor Munkin via Tarantool-patches
                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 25+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2023-07-21  8:12 UTC (permalink / raw)
  To: Sergey Kaplun, Sergey Bronnikov; +Cc: tarantool-patches

Before the patch all tests (except <lj-603-err-snap-restore.test.lua>)
in tarantool-tests suite terminate their execution via <os.exit> with
the status depending on the test results. However, the second argument
of <os.exit> was omitted and Lua universe was not properly finalized as
a result. This behaviour becomes a problem, when LuaJIT is build with
LUAJIT_USE_SYSMALLOC option and AddressSanitizer support enabled, since
the sanitizer starts reporting false positive errors about the memory
allocations without the corresponding memory releases. To resolve these
errors, the second parameter to each <os.exit> call terminating the test
has to be added.

To avoid loss of the aforementioned parameter in future, <test:done>
helper has been added to the TAP module. Depending on the single
parameter, the new helper either properly finalize the test being run,
or simply checks all the test assertions and raises an error if any of
them fail. The latter case is added especially to handle the specifics
of <lj-603-err-snap-restore.test.lua> and still check that everything
works fine.

Needed for tarantool/tarantool#5878

Signed-off-by: Igor Munkin <imun@tarantool.org>
---
 .../arm64-ccall-fp-convention.test.lua            |  2 +-
 test/tarantool-tests/bc-jit-unpatching.test.lua   |  2 +-
 .../c-library-path-length.test.lua                |  2 +-
 .../fix-bit-shift-generation.test.lua             |  2 +-
 test/tarantool-tests/fix-cdata-concat.test.lua    |  2 +-
 test/tarantool-tests/fix-emit-rma.test.lua        |  2 +-
 .../fix-fold-simplify-conv-sext.test.lua          |  2 +-
 test/tarantool-tests/fix-gc-setupvalue.test.lua   |  2 +-
 .../fix-slot-check-for-mm-record.test.lua         |  2 +-
 .../gh-3196-incorrect-string-length.test.lua      |  2 +-
 test/tarantool-tests/gh-4199-gc64-fuse.test.lua   |  2 +-
 .../tarantool-tests/gh-4427-ffi-sandwich.test.lua |  2 +-
 .../gh-4476-fix-string-find-recording.test.lua    |  2 +-
 .../gh-4773-tonumber-fail-on-NUL-char.test.lua    |  2 +-
 .../gh-5813-resolving-of-c-symbols.test.lua       |  2 +-
 .../gh-6065-jit-library-smoke-tests.test.lua      |  2 +-
 ...6084-missed-carg1-in-bctsetr-fallback.test.lua |  2 +-
 .../gh-6096-external-unwinding-on-arm64.test.lua  |  2 +-
 ...-6098-fix-side-exit-patching-on-arm64.test.lua |  2 +-
 test/tarantool-tests/gh-6163-min-max.test.lua     |  2 +-
 test/tarantool-tests/gh-6189-cur_L.test.lua       |  2 +-
 ...27-bytecode-allocator-for-comparisons.test.lua |  2 +-
 .../gh-6371-string-char-no-arg.test.lua           |  2 +-
 .../gh-6782-stitching-in-vmevent-handler.test.lua |  2 +-
 .../gh-6976-narrowing-of-unary-minus.test.lua     |  2 +-
 ...-7264-add-proto-trace-sysprof-default.test.lua |  2 +-
 .../tarantool-tests/gh-7745-oom-on-trace.test.lua |  2 +-
 .../lj-350-sload-typecheck.test.lua               |  2 +-
 .../lj-351-print-tostring-number.test.lua         |  2 +-
 .../lj-356-ir-khash-non-string-obj.test.lua       |  2 +-
 test/tarantool-tests/lj-357-arm64-hrefk.test.lua  |  2 +-
 .../lj-366-strtab-correct-size.test.lua           |  2 +-
 .../lj-375-ir-bufput-signed-char.test.lua         |  2 +-
 .../lj-378-string-format-c-null-char.test.lua     |  2 +-
 .../lj-408-tonumber-cdata-record.test.lua         |  2 +-
 .../lj-416-xor-before-jcc.test.lua                |  2 +-
 .../lj-418-assert-any-type.test.lua               |  2 +-
 ...j-426-arm64-incorrect-check-closed-uv.test.lua |  2 +-
 test/tarantool-tests/lj-430-maxirconst.test.lua   |  2 +-
 ...-438-arm64-constant-rematerialization.test.lua |  2 +-
 .../lj-445-fix-memory-probing-allocator.test.lua  |  2 +-
 test/tarantool-tests/lj-463-os-date-oom.test.lua  |  2 +-
 .../lj-494-table-chain-infinite-loop.test.lua     |  2 +-
 .../lj-505-fold-no-strref-for-ptrdiff.test.lua    |  2 +-
 .../lj-512-profiler-hook-finalizers.test.lua      |  2 +-
 .../lj-524-fold-conv-respect-src-irt.test.lua     |  2 +-
 test/tarantool-tests/lj-528-tonumber-0.test.lua   |  2 +-
 .../lj-556-fix-loop-realignment.test.lua          |  2 +-
 .../lj-574-overflow-unpack.test.lua               |  2 +-
 .../lj-584-bad-renames-for-sunk-values.test.lua   |  2 +-
 .../lj-586-debug-non-string-error.test.lua        |  2 +-
 .../lj-601-fix-gc-finderrfunc.test.lua            |  2 +-
 .../lj-603-err-snap-restore.test.lua              | 15 ++++++++-------
 .../lj-671-arm64-assert-after-mremap.test.lua     |  2 +-
 .../lj-672-cdata-allocation-recording.test.lua    |  2 +-
 .../lj-688-snap-ir-rename.test.lua                |  2 +-
 .../lj-695-ffi-vararg-call.test.lua               |  2 +-
 .../lj-698-arm-pcall-panic.test.lua               |  2 +-
 .../lj-704-bc-varg-use-def.test.lua               |  2 +-
 .../lj-726-profile-flush-close.test.lua           |  2 +-
 .../lj-727-lightuserdata-itern.test.lua           |  2 +-
 .../lj-735-io-close-on-closed-file.test.lua       |  2 +-
 test/tarantool-tests/lj-762-pcall-no-arg.test.lua |  2 +-
 .../lj-819-fix-missing-uclo.test.lua              |  2 +-
 .../lj-864-varg-rec-base-offset.test.lua          |  2 +-
 test/tarantool-tests/lj-906-fix-err-mem.test.lua  |  2 +-
 test/tarantool-tests/lj-981-folding-0.test.lua    |  2 +-
 ...994-instable-types-during-loop-unroll.test.lua |  2 +-
 test/tarantool-tests/lj-flush-on-trace.test.lua   |  2 +-
 test/tarantool-tests/math-modf.test.lua           |  2 ++
 .../misclib-getmetrics-lapi.test.lua              |  2 +-
 .../tarantool-tests/misclib-memprof-lapi.test.lua |  2 +-
 .../tarantool-tests/misclib-sysprof-lapi.test.lua |  2 +-
 .../tarantool-tests/or-144-gc64-asmref-l.test.lua |  2 +-
 .../or-232-unsink-64-kptr.test.lua                |  2 +-
 .../or-94-arm64-ir-ahuvload-bool.test.lua         |  2 +-
 test/tarantool-tests/tap.lua                      | 14 +++++++++++++-
 .../tonumber-negative-non-decimal-base.test.lua   |  2 +-
 test/tarantool-tests/tools-utils-avl.test.lua     |  2 +-
 test/tarantool-tests/unit-jit-parse.test.lua      |  2 +-
 80 files changed, 100 insertions(+), 85 deletions(-)

diff --git a/test/tarantool-tests/arm64-ccall-fp-convention.test.lua b/test/tarantool-tests/arm64-ccall-fp-convention.test.lua
index 8307e8b1..c58ba697 100644
--- a/test/tarantool-tests/arm64-ccall-fp-convention.test.lua
+++ b/test/tarantool-tests/arm64-ccall-fp-convention.test.lua
@@ -62,4 +62,4 @@ test:ok(assert_sz12(sz12_222, {2, 2, 2}), '2 structures as args')
 local sz12_333 = ffi_ccall.sum3sz12(sz12_111, sz12_111, sz12_111)
 test:ok(assert_sz12(sz12_333, {3, 3, 3}), '3 structures as args')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/bc-jit-unpatching.test.lua b/test/tarantool-tests/bc-jit-unpatching.test.lua
index f4f148c9..752fafac 100644
--- a/test/tarantool-tests/bc-jit-unpatching.test.lua
+++ b/test/tarantool-tests/bc-jit-unpatching.test.lua
@@ -22,4 +22,4 @@ f(5)
 test:ok(utils.frontend.hasbc(load(string.dump(f)), ret1bc),
         'bytecode unpatching is OK')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/c-library-path-length.test.lua b/test/tarantool-tests/c-library-path-length.test.lua
index 4f1e6602..63f3b695 100644
--- a/test/tarantool-tests/c-library-path-length.test.lua
+++ b/test/tarantool-tests/c-library-path-length.test.lua
@@ -11,4 +11,4 @@ local res, err = package.loadlib(long_path, 'func')
 test:ok(res == nil, 'loaded library with a too large path')
 test:like(err, 'path too long', 'incorrect error')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/fix-bit-shift-generation.test.lua b/test/tarantool-tests/fix-bit-shift-generation.test.lua
index d8e8a9b4..9704f32c 100644
--- a/test/tarantool-tests/fix-bit-shift-generation.test.lua
+++ b/test/tarantool-tests/fix-bit-shift-generation.test.lua
@@ -44,4 +44,4 @@ for i = 1, NTESTS do
   test:ok(result[i] == shl(1ULL, i + 32), 'valid rol')
 end
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/fix-cdata-concat.test.lua b/test/tarantool-tests/fix-cdata-concat.test.lua
index df069e58..2ea37b02 100644
--- a/test/tarantool-tests/fix-cdata-concat.test.lua
+++ b/test/tarantool-tests/fix-cdata-concat.test.lua
@@ -18,4 +18,4 @@ debug.getmetatable(1LL).__concat = function(a, b)
 end
 test:ok(1LL .. 2LL == '1LL2LL', 'cdata concatenation with defined metamethod')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/fix-emit-rma.test.lua b/test/tarantool-tests/fix-emit-rma.test.lua
index 1f8e66f4..42804447 100644
--- a/test/tarantool-tests/fix-emit-rma.test.lua
+++ b/test/tarantool-tests/fix-emit-rma.test.lua
@@ -101,4 +101,4 @@ end
 -- trace.
 test:ok(true, 'IR_OBAR emit_rma check correctness')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/fix-fold-simplify-conv-sext.test.lua b/test/tarantool-tests/fix-fold-simplify-conv-sext.test.lua
index 60eb3e7c..d5356816 100644
--- a/test/tarantool-tests/fix-fold-simplify-conv-sext.test.lua
+++ b/test/tarantool-tests/fix-fold-simplify-conv-sext.test.lua
@@ -32,4 +32,4 @@ for i = 1, NTEST do
   test:ok(results[i] == expected[i], 'correct cdata indexing')
 end
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/fix-gc-setupvalue.test.lua b/test/tarantool-tests/fix-gc-setupvalue.test.lua
index 21acc9bf..6b57283f 100644
--- a/test/tarantool-tests/fix-gc-setupvalue.test.lua
+++ b/test/tarantool-tests/fix-gc-setupvalue.test.lua
@@ -58,4 +58,4 @@ for i = 1, 1e2 do local _ = {string.rep('0', i)} end
 
 test:ok(_G.parent() == 42, 'correct set up of upvalue')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua b/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua
index 6161747f..602426ac 100644
--- a/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua
+++ b/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua
@@ -79,4 +79,4 @@ end
 jit.opt.start('hotloop=1', 'maxrecord=2048')
 
 test:ok(try(require('ffi').abi('gc64')))
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-3196-incorrect-string-length.test.lua b/test/tarantool-tests/gh-3196-incorrect-string-length.test.lua
index 0342c832..b82029f6 100644
--- a/test/tarantool-tests/gh-3196-incorrect-string-length.test.lua
+++ b/test/tarantool-tests/gh-3196-incorrect-string-length.test.lua
@@ -12,4 +12,4 @@ test:is(h:len(), 20)
 h = "\x0F\x93\xE2\x1C\xCA\xDE\x28\x08\x26\x01\xED\x0A\x2F\xE4\x21\x02\x97\x77\xD9\x3E"
 test:is(h:len(), 20)
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-4199-gc64-fuse.test.lua b/test/tarantool-tests/gh-4199-gc64-fuse.test.lua
index 4513d43b..ca050cf0 100644
--- a/test/tarantool-tests/gh-4199-gc64-fuse.test.lua
+++ b/test/tarantool-tests/gh-4199-gc64-fuse.test.lua
@@ -83,4 +83,4 @@ for n = 1, 100 do
 end
 
 test:ok(ok, 'IR constant fusion')
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-4427-ffi-sandwich.test.lua b/test/tarantool-tests/gh-4427-ffi-sandwich.test.lua
index 677a6085..34139d86 100644
--- a/test/tarantool-tests/gh-4427-ffi-sandwich.test.lua
+++ b/test/tarantool-tests/gh-4427-ffi-sandwich.test.lua
@@ -59,4 +59,4 @@ for _, subtest in pairs(cases) do
   test[subtest.test](test, output, subtest.expected, subtest.message)
 end
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-4476-fix-string-find-recording.test.lua b/test/tarantool-tests/gh-4476-fix-string-find-recording.test.lua
index 56776192..c4acdd3d 100644
--- a/test/tarantool-tests/gh-4476-fix-string-find-recording.test.lua
+++ b/test/tarantool-tests/gh-4476-fix-string-find-recording.test.lua
@@ -76,4 +76,4 @@ until not e
 
 test:is(count_vm, count_jit)
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-4773-tonumber-fail-on-NUL-char.test.lua b/test/tarantool-tests/gh-4773-tonumber-fail-on-NUL-char.test.lua
index 112c491e..7bacc0f9 100644
--- a/test/tarantool-tests/gh-4773-tonumber-fail-on-NUL-char.test.lua
+++ b/test/tarantool-tests/gh-4773-tonumber-fail-on-NUL-char.test.lua
@@ -19,4 +19,4 @@ test:is(tonumber(t.zero), 0)
 test:is(tonumber(t.zero .. t.tail), nil)
 test:is(tonumber(t.zero .. t.null .. t.tail), nil)
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-5813-resolving-of-c-symbols.test.lua b/test/tarantool-tests/gh-5813-resolving-of-c-symbols.test.lua
index 1209d288..30b8a3ca 100644
--- a/test/tarantool-tests/gh-5813-resolving-of-c-symbols.test.lua
+++ b/test/tarantool-tests/gh-5813-resolving-of-c-symbols.test.lua
@@ -95,4 +95,4 @@ test:ok(tree_contains(symbols.cfunc, "allocate_string"))
 -- perform a test in that case, since it is impossible to load Lua module
 -- written in C if it doesn't have a .dynsym segment.
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-6065-jit-library-smoke-tests.test.lua b/test/tarantool-tests/gh-6065-jit-library-smoke-tests.test.lua
index 5d7fd7e2..8105c3ba 100644
--- a/test/tarantool-tests/gh-6065-jit-library-smoke-tests.test.lua
+++ b/test/tarantool-tests/gh-6065-jit-library-smoke-tests.test.lua
@@ -10,4 +10,4 @@ test:plan(1)
 -- as a second argument to the assertion.
 test:ok(pcall(jit.on))
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-6084-missed-carg1-in-bctsetr-fallback.test.lua b/test/tarantool-tests/gh-6084-missed-carg1-in-bctsetr-fallback.test.lua
index 10db7603..5cc9416a 100644
--- a/test/tarantool-tests/gh-6084-missed-carg1-in-bctsetr-fallback.test.lua
+++ b/test/tarantool-tests/gh-6084-missed-carg1-in-bctsetr-fallback.test.lua
@@ -24,4 +24,4 @@ local res = table.move(t, 1, 1, 2)
 test:ok(t == res, 'table.move returns the same table')
 test:ok(t[1] == t[2], 'table.move is correct')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-6096-external-unwinding-on-arm64.test.lua b/test/tarantool-tests/gh-6096-external-unwinding-on-arm64.test.lua
index cdeea441..097e771c 100644
--- a/test/tarantool-tests/gh-6096-external-unwinding-on-arm64.test.lua
+++ b/test/tarantool-tests/gh-6096-external-unwinding-on-arm64.test.lua
@@ -10,4 +10,4 @@ test:plan(1)
 local res = pcall(require, 'not-existing-module')
 test:ok(res == false, 'successful unwinding in pcall')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-6098-fix-side-exit-patching-on-arm64.test.lua b/test/tarantool-tests/gh-6098-fix-side-exit-patching-on-arm64.test.lua
index cfcc6adb..93db3041 100644
--- a/test/tarantool-tests/gh-6098-fix-side-exit-patching-on-arm64.test.lua
+++ b/test/tarantool-tests/gh-6098-fix-side-exit-patching-on-arm64.test.lua
@@ -129,4 +129,4 @@ pxcall(cbool, false)
 cbool(false)
 
 test:ok(true)
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-6163-min-max.test.lua b/test/tarantool-tests/gh-6163-min-max.test.lua
index 882cb1a0..63437955 100644
--- a/test/tarantool-tests/gh-6163-min-max.test.lua
+++ b/test/tarantool-tests/gh-6163-min-max.test.lua
@@ -262,4 +262,4 @@ end
 -- expected: 1.1 1.1 1.1 1.1
 test:ok(array_is_consistent(result), 'max: fold_kfold_numarith')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-6189-cur_L.test.lua b/test/tarantool-tests/gh-6189-cur_L.test.lua
index a5096a7c..d6b8eef0 100644
--- a/test/tarantool-tests/gh-6189-cur_L.test.lua
+++ b/test/tarantool-tests/gh-6189-cur_L.test.lua
@@ -28,4 +28,4 @@ assert(pcall(libcur_L.error_from_other_thread) == false, "return from error")
 cbool(false)
 
 test:ok(true)
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-6227-bytecode-allocator-for-comparisons.test.lua b/test/tarantool-tests/gh-6227-bytecode-allocator-for-comparisons.test.lua
index da399bcf..07152744 100644
--- a/test/tarantool-tests/gh-6227-bytecode-allocator-for-comparisons.test.lua
+++ b/test/tarantool-tests/gh-6227-bytecode-allocator-for-comparisons.test.lua
@@ -54,4 +54,4 @@ for _ = 1, 3 do
 end
 
 test:ok(true)
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-6371-string-char-no-arg.test.lua b/test/tarantool-tests/gh-6371-string-char-no-arg.test.lua
index 90121860..48a5857d 100644
--- a/test/tarantool-tests/gh-6371-string-char-no-arg.test.lua
+++ b/test/tarantool-tests/gh-6371-string-char-no-arg.test.lua
@@ -27,4 +27,4 @@ for i = 1, NTEST do
   test:ok(results[i] == '', 'correct recording of string.char() without args')
 end
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-6782-stitching-in-vmevent-handler.test.lua b/test/tarantool-tests/gh-6782-stitching-in-vmevent-handler.test.lua
index 385e7648..afca6c40 100644
--- a/test/tarantool-tests/gh-6782-stitching-in-vmevent-handler.test.lua
+++ b/test/tarantool-tests/gh-6782-stitching-in-vmevent-handler.test.lua
@@ -32,4 +32,4 @@ require('jit.bc').dump(loadstring(string.dump(fibb)), {
 -- `jit.bc` functions inside.
 test:ok(fibb(2) == 1, 'run compiled function inside vmevent handler')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-6976-narrowing-of-unary-minus.test.lua b/test/tarantool-tests/gh-6976-narrowing-of-unary-minus.test.lua
index 40387cca..31890965 100644
--- a/test/tarantool-tests/gh-6976-narrowing-of-unary-minus.test.lua
+++ b/test/tarantool-tests/gh-6976-narrowing-of-unary-minus.test.lua
@@ -48,4 +48,4 @@ test:ok(check(function()
   return res
 end), 'assertion guard fail')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-7264-add-proto-trace-sysprof-default.test.lua b/test/tarantool-tests/gh-7264-add-proto-trace-sysprof-default.test.lua
index 9cce32cb..c1d68e3c 100644
--- a/test/tarantool-tests/gh-7264-add-proto-trace-sysprof-default.test.lua
+++ b/test/tarantool-tests/gh-7264-add-proto-trace-sysprof-default.test.lua
@@ -44,4 +44,4 @@ assert(misc.sysprof.start({ mode = 'D' }))
 allocate()
 test:ok(misc.sysprof.stop(), 'trace record in sysprof runtime')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/gh-7745-oom-on-trace.test.lua b/test/tarantool-tests/gh-7745-oom-on-trace.test.lua
index 81be445d..9ac41ac7 100644
--- a/test/tarantool-tests/gh-7745-oom-on-trace.test.lua
+++ b/test/tarantool-tests/gh-7745-oom-on-trace.test.lua
@@ -38,4 +38,4 @@ collectgarbage()
 
 test:ok(res == false)
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-350-sload-typecheck.test.lua b/test/tarantool-tests/lj-350-sload-typecheck.test.lua
index 5b25864d..33380170 100644
--- a/test/tarantool-tests/lj-350-sload-typecheck.test.lua
+++ b/test/tarantool-tests/lj-350-sload-typecheck.test.lua
@@ -41,4 +41,4 @@ jit.off()
 
 test:ok(not traceinfo(2), 'the second trace should not be compiled')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-351-print-tostring-number.test.lua b/test/tarantool-tests/lj-351-print-tostring-number.test.lua
index b7041f2a..c67c6859 100644
--- a/test/tarantool-tests/lj-351-print-tostring-number.test.lua
+++ b/test/tarantool-tests/lj-351-print-tostring-number.test.lua
@@ -26,4 +26,4 @@ for _, subtest in pairs(cases) do
           ('subtest is OK for %s type'):format(subtest.typename))
 end
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-356-ir-khash-non-string-obj.test.lua b/test/tarantool-tests/lj-356-ir-khash-non-string-obj.test.lua
index 9977205d..5159ac32 100644
--- a/test/tarantool-tests/lj-356-ir-khash-non-string-obj.test.lua
+++ b/test/tarantool-tests/lj-356-ir-khash-non-string-obj.test.lua
@@ -90,4 +90,4 @@ for i = 1, N_ITERATIONS do
   test:ok(result_tab[i] == MAGIC, 'correct hash lookup from the table')
 end
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-357-arm64-hrefk.test.lua b/test/tarantool-tests/lj-357-arm64-hrefk.test.lua
index d7e9c85e..8db8bbfc 100644
--- a/test/tarantool-tests/lj-357-arm64-hrefk.test.lua
+++ b/test/tarantool-tests/lj-357-arm64-hrefk.test.lua
@@ -29,4 +29,4 @@ end
 test:is(t.hrefk, -START)
 test:is(t[t.hrefk], STOP)
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-366-strtab-correct-size.test.lua b/test/tarantool-tests/lj-366-strtab-correct-size.test.lua
index aa4e72e7..8a97a441 100644
--- a/test/tarantool-tests/lj-366-strtab-correct-size.test.lua
+++ b/test/tarantool-tests/lj-366-strtab-correct-size.test.lua
@@ -202,4 +202,4 @@ test:ok(sym_is_found == true, 'symbol is found')
 local ret = os.remove(elf_filename)
 assert(ret == true, 'cannot remove an object file')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-375-ir-bufput-signed-char.test.lua b/test/tarantool-tests/lj-375-ir-bufput-signed-char.test.lua
index f600d898..9f913eba 100644
--- a/test/tarantool-tests/lj-375-ir-bufput-signed-char.test.lua
+++ b/test/tarantool-tests/lj-375-ir-bufput-signed-char.test.lua
@@ -29,4 +29,4 @@ for i = 1, NTEST do
   test:ok(results[i] == 0xff, 'correct 0xff signed char assembling')
 end
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-378-string-format-c-null-char.test.lua b/test/tarantool-tests/lj-378-string-format-c-null-char.test.lua
index 15cefadf..7632c7fd 100644
--- a/test/tarantool-tests/lj-378-string-format-c-null-char.test.lua
+++ b/test/tarantool-tests/lj-378-string-format-c-null-char.test.lua
@@ -8,4 +8,4 @@ test:plan(1)
 -- See also https://github.com/LuaJIT/LuaJIT/issues/378.
 
 test:is(string.format('%c', 0), '\0', 'string.format %c on null char')
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-408-tonumber-cdata-record.test.lua b/test/tarantool-tests/lj-408-tonumber-cdata-record.test.lua
index bdd0aaaa..3a7e1f28 100644
--- a/test/tarantool-tests/lj-408-tonumber-cdata-record.test.lua
+++ b/test/tarantool-tests/lj-408-tonumber-cdata-record.test.lua
@@ -41,4 +41,4 @@ check(0LL)
 test:ok(check(0LL), 'recorded with 0LL and converted for 0LL')
 test:ok(not check(NULL), 'recorded with 0LL and not converted for NULL')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-416-xor-before-jcc.test.lua b/test/tarantool-tests/lj-416-xor-before-jcc.test.lua
index 861114e8..605bb92a 100644
--- a/test/tarantool-tests/lj-416-xor-before-jcc.test.lua
+++ b/test/tarantool-tests/lj-416-xor-before-jcc.test.lua
@@ -97,4 +97,4 @@ for _ = 1, 3 do
 end
 test:ok(true, 'impossible branch is not taken')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-418-assert-any-type.test.lua b/test/tarantool-tests/lj-418-assert-any-type.test.lua
index 24683554..51b21ed8 100644
--- a/test/tarantool-tests/lj-418-assert-any-type.test.lua
+++ b/test/tarantool-tests/lj-418-assert-any-type.test.lua
@@ -15,4 +15,4 @@ xpcall(assert, function(obj)
   test:ok(obj == retv, 'xpcall error handler function get non-string argument')
 end, false, retv)
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-426-arm64-incorrect-check-closed-uv.test.lua b/test/tarantool-tests/lj-426-arm64-incorrect-check-closed-uv.test.lua
index 4cdf1211..a689ed60 100644
--- a/test/tarantool-tests/lj-426-arm64-incorrect-check-closed-uv.test.lua
+++ b/test/tarantool-tests/lj-426-arm64-incorrect-check-closed-uv.test.lua
@@ -36,4 +36,4 @@ while (misc.getmetrics().gc_steps_atomic == old_steps_atomic) do
 end
 
 test:ok(true)
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-430-maxirconst.test.lua b/test/tarantool-tests/lj-430-maxirconst.test.lua
index 531acd7d..903fad8e 100644
--- a/test/tarantool-tests/lj-430-maxirconst.test.lua
+++ b/test/tarantool-tests/lj-430-maxirconst.test.lua
@@ -44,4 +44,4 @@ irconst4()
 jit.off()
 test:ok(not traceinfo(2), 'trace should not appear due to maxirconst limit')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-438-arm64-constant-rematerialization.test.lua b/test/tarantool-tests/lj-438-arm64-constant-rematerialization.test.lua
index 0a59209c..9886fe09 100644
--- a/test/tarantool-tests/lj-438-arm64-constant-rematerialization.test.lua
+++ b/test/tarantool-tests/lj-438-arm64-constant-rematerialization.test.lua
@@ -102,4 +102,4 @@ wrap()
 
 test:ok(true, 'the resulting trace is correct')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-445-fix-memory-probing-allocator.test.lua b/test/tarantool-tests/lj-445-fix-memory-probing-allocator.test.lua
index a228651b..da924bb0 100644
--- a/test/tarantool-tests/lj-445-fix-memory-probing-allocator.test.lua
+++ b/test/tarantool-tests/lj-445-fix-memory-probing-allocator.test.lua
@@ -47,4 +47,4 @@ for _ = 1, MAX_GB do
   end
 end
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-463-os-date-oom.test.lua b/test/tarantool-tests/lj-463-os-date-oom.test.lua
index 0861ce14..e431d19d 100644
--- a/test/tarantool-tests/lj-463-os-date-oom.test.lua
+++ b/test/tarantool-tests/lj-463-os-date-oom.test.lua
@@ -14,4 +14,4 @@ end
 
 test:ok(true, 'os.date() finished without OOM')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-494-table-chain-infinite-loop.test.lua b/test/tarantool-tests/lj-494-table-chain-infinite-loop.test.lua
index aae90e8a..3dd17e7a 100644
--- a/test/tarantool-tests/lj-494-table-chain-infinite-loop.test.lua
+++ b/test/tarantool-tests/lj-494-table-chain-infinite-loop.test.lua
@@ -174,4 +174,4 @@ for c, v in pairs(victims) do
 end
 test:ok(true, "table keys collisions are resolved properly (no assertions failed)")
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-505-fold-no-strref-for-ptrdiff.test.lua b/test/tarantool-tests/lj-505-fold-no-strref-for-ptrdiff.test.lua
index fec08b30..a40e7796 100644
--- a/test/tarantool-tests/lj-505-fold-no-strref-for-ptrdiff.test.lua
+++ b/test/tarantool-tests/lj-505-fold-no-strref-for-ptrdiff.test.lua
@@ -18,4 +18,4 @@ for _ = 1, 20 do
 end
 test:ok(true, "string.find offset aritmetics wasn't broken while recording")
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-512-profiler-hook-finalizers.test.lua b/test/tarantool-tests/lj-512-profiler-hook-finalizers.test.lua
index f7ee344f..a282a10f 100644
--- a/test/tarantool-tests/lj-512-profiler-hook-finalizers.test.lua
+++ b/test/tarantool-tests/lj-512-profiler-hook-finalizers.test.lua
@@ -28,4 +28,4 @@ profile.stop()
 test:ok(nsamples >= 0.5 * (finish - start) * 1e3 / INTERVAL,
         'profiler sampling')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-524-fold-conv-respect-src-irt.test.lua b/test/tarantool-tests/lj-524-fold-conv-respect-src-irt.test.lua
index a13e5d55..70d330ac 100644
--- a/test/tarantool-tests/lj-524-fold-conv-respect-src-irt.test.lua
+++ b/test/tarantool-tests/lj-524-fold-conv-respect-src-irt.test.lua
@@ -21,4 +21,4 @@ end
 
 test:is(tonumber(sq), math.fmod(math.pow(42, 8), math.pow(2, 32)))
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-528-tonumber-0.test.lua b/test/tarantool-tests/lj-528-tonumber-0.test.lua
index 27f17e54..8b4c0832 100644
--- a/test/tarantool-tests/lj-528-tonumber-0.test.lua
+++ b/test/tarantool-tests/lj-528-tonumber-0.test.lua
@@ -10,4 +10,4 @@ test:plan(1)
 -- As numbers -0 equals to 0, so convert it back to string.
 test:ok(tostring(tonumber('-0')) == '-0', 'correct "-0" string parsing')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-556-fix-loop-realignment.test.lua b/test/tarantool-tests/lj-556-fix-loop-realignment.test.lua
index b94bd3e9..89f70693 100644
--- a/test/tarantool-tests/lj-556-fix-loop-realignment.test.lua
+++ b/test/tarantool-tests/lj-556-fix-loop-realignment.test.lua
@@ -17,4 +17,4 @@ while s > 0 do
 end
 
 test:ok(true, 'loop is compiled and ran successfully')
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-574-overflow-unpack.test.lua b/test/tarantool-tests/lj-574-overflow-unpack.test.lua
index 6715d947..671ccddd 100644
--- a/test/tarantool-tests/lj-574-overflow-unpack.test.lua
+++ b/test/tarantool-tests/lj-574-overflow-unpack.test.lua
@@ -9,4 +9,4 @@ test:plan(1)
 local r, e = pcall(unpack, {}, 0, 2^31 - 1)
 test:ok(not r and e == 'too many results to unpack', 'overflow check in unpack')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-584-bad-renames-for-sunk-values.test.lua b/test/tarantool-tests/lj-584-bad-renames-for-sunk-values.test.lua
index e0c3e577..cb0623b1 100644
--- a/test/tarantool-tests/lj-584-bad-renames-for-sunk-values.test.lua
+++ b/test/tarantool-tests/lj-584-bad-renames-for-sunk-values.test.lua
@@ -96,4 +96,4 @@ end, function()
   test:fail('Invalid Lua stack has been restored')
 end)
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-586-debug-non-string-error.test.lua b/test/tarantool-tests/lj-586-debug-non-string-error.test.lua
index c00301a1..67869708 100644
--- a/test/tarantool-tests/lj-586-debug-non-string-error.test.lua
+++ b/test/tarantool-tests/lj-586-debug-non-string-error.test.lua
@@ -44,4 +44,4 @@ EOF]]):format(luabin, magic)
 
 local res = io.popen(cmd):read('*all'):gsub('%s+$', '')
 test:ok(res == expected, 'handle non-string error in debug.debug()')
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-601-fix-gc-finderrfunc.test.lua b/test/tarantool-tests/lj-601-fix-gc-finderrfunc.test.lua
index 2122c7a0..1549257d 100644
--- a/test/tarantool-tests/lj-601-fix-gc-finderrfunc.test.lua
+++ b/test/tarantool-tests/lj-601-fix-gc-finderrfunc.test.lua
@@ -35,4 +35,4 @@ a = nil
 -- frame. As a result, error is raised in __gc metamethod above.
 test:ok(mixcframe.test_handle_err(), 'error in __gc is successfully handled')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-603-err-snap-restore.test.lua b/test/tarantool-tests/lj-603-err-snap-restore.test.lua
index a6c831ed..791107ba 100644
--- a/test/tarantool-tests/lj-603-err-snap-restore.test.lua
+++ b/test/tarantool-tests/lj-603-err-snap-restore.test.lua
@@ -55,16 +55,17 @@ end
 -- restoration from the snapshot.
 if require('ffi').abi('gc64') then
   -- luacheck: no unused
-  local _, _, _, _, _, _
+  local _, _, _, _, _
   do_test()
 else
   -- luacheck: no unused
-  local _, _, _, _
+  local _, _, _, _, _, _, _, _, _, _, _, _, _
   do_test()
 end
 
--- XXX: Don't use `os.exit()` here by intention. When error on
--- snap restoration is raised, `err_unwind()` doesn't stop on
--- correct cframe. So later, on exit from VM this corrupted cframe
--- chain shows itself. `os.exit()` literally calls `exit()` and
--- doesn't show the issue.
+-- XXX: Don't force `test:done()` finish test with `os.exit()` by
+-- intention. When error on snapshot restoration is raised,
+-- `err_unwind()` doesn't stop on the correct cframe. So later, on
+-- exit from VM this corrupted cframe chain shows itself.
+-- `os.exit()` just calls `exit()` and doesn't show the issue.
+test:done(false)
diff --git a/test/tarantool-tests/lj-671-arm64-assert-after-mremap.test.lua b/test/tarantool-tests/lj-671-arm64-assert-after-mremap.test.lua
index 0558cbe3..74ade1db 100644
--- a/test/tarantool-tests/lj-671-arm64-assert-after-mremap.test.lua
+++ b/test/tarantool-tests/lj-671-arm64-assert-after-mremap.test.lua
@@ -21,4 +21,4 @@ local DEFAULT_MMAP_THRESHOLD = 128 * 1024
 local s = string.rep('x', DEFAULT_MMAP_THRESHOLD)..'x'
 test:ok(s)
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-672-cdata-allocation-recording.test.lua b/test/tarantool-tests/lj-672-cdata-allocation-recording.test.lua
index 1d6b19ba..22deac5d 100644
--- a/test/tarantool-tests/lj-672-cdata-allocation-recording.test.lua
+++ b/test/tarantool-tests/lj-672-cdata-allocation-recording.test.lua
@@ -28,4 +28,4 @@ end
 
 test:ok(traceinfo(1), 'new trace created')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-688-snap-ir-rename.test.lua b/test/tarantool-tests/lj-688-snap-ir-rename.test.lua
index 46bddd9f..807e0811 100644
--- a/test/tarantool-tests/lj-688-snap-ir-rename.test.lua
+++ b/test/tarantool-tests/lj-688-snap-ir-rename.test.lua
@@ -57,4 +57,4 @@ end
 test:ok(true, 'IR_RENAME is fine')
 -- `test:check() and 0 or 1` is replaced with just test:check()
 -- here, because otherwise, it affects the renaming process.
-os.exit(test:check())
+test:done(true)
diff --git a/test/tarantool-tests/lj-695-ffi-vararg-call.test.lua b/test/tarantool-tests/lj-695-ffi-vararg-call.test.lua
index 04be1998..496a4c0d 100644
--- a/test/tarantool-tests/lj-695-ffi-vararg-call.test.lua
+++ b/test/tarantool-tests/lj-695-ffi-vararg-call.test.lua
@@ -13,4 +13,4 @@ local result = ffi.string(str)
 test:is(#result, strlen)
 test:is(result, 'try vararg function: imun:9.00(9) - 18446744073709551615')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-698-arm-pcall-panic.test.lua b/test/tarantool-tests/lj-698-arm-pcall-panic.test.lua
index 88476d3e..5f9d193a 100644
--- a/test/tarantool-tests/lj-698-arm-pcall-panic.test.lua
+++ b/test/tarantool-tests/lj-698-arm-pcall-panic.test.lua
@@ -15,4 +15,4 @@ local runner = ffi.cast("int (*)(int, int, int, int, int, int, int, int, int)",
 local st = pcall(runner, 1, 1, 1, 1, 1, 1, 1, 1, 1)
 test:ok(not st, 'error handling completed correctly')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-704-bc-varg-use-def.test.lua b/test/tarantool-tests/lj-704-bc-varg-use-def.test.lua
index e6a0973b..93455e3c 100644
--- a/test/tarantool-tests/lj-704-bc-varg-use-def.test.lua
+++ b/test/tarantool-tests/lj-704-bc-varg-use-def.test.lua
@@ -90,4 +90,4 @@ wrap_ret_bc(ON_TRACE_VALUE)
 
 test:ok(result ~= 0, 'use-def analysis for FUNCV with jump before BC_VARG')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-726-profile-flush-close.test.lua b/test/tarantool-tests/lj-726-profile-flush-close.test.lua
index a3f8def9..36cca43d 100644
--- a/test/tarantool-tests/lj-726-profile-flush-close.test.lua
+++ b/test/tarantool-tests/lj-726-profile-flush-close.test.lua
@@ -26,4 +26,4 @@ test:ok(f:read(0), 'profile output was flushed and closed')
 
 assert(os.remove(TEST_FILE))
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-727-lightuserdata-itern.test.lua b/test/tarantool-tests/lj-727-lightuserdata-itern.test.lua
index 3e459f43..bb01f122 100644
--- a/test/tarantool-tests/lj-727-lightuserdata-itern.test.lua
+++ b/test/tarantool-tests/lj-727-lightuserdata-itern.test.lua
@@ -42,4 +42,4 @@ end)
 test.strict = true
 test:is_deeply(visited, t, 'userdata node is visited')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-735-io-close-on-closed-file.test.lua b/test/tarantool-tests/lj-735-io-close-on-closed-file.test.lua
index 2a590df0..a23aa0d4 100644
--- a/test/tarantool-tests/lj-735-io-close-on-closed-file.test.lua
+++ b/test/tarantool-tests/lj-735-io-close-on-closed-file.test.lua
@@ -21,4 +21,4 @@ test:ok(err:match('attempt to use a closed file'), 'correct error message')
 
 assert(os.remove(TEST_FILE))
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-762-pcall-no-arg.test.lua b/test/tarantool-tests/lj-762-pcall-no-arg.test.lua
index 6cbfe707..db16c3dd 100644
--- a/test/tarantool-tests/lj-762-pcall-no-arg.test.lua
+++ b/test/tarantool-tests/lj-762-pcall-no-arg.test.lua
@@ -12,4 +12,4 @@ local result, err = pcall(pcall)
 test:ok(not result, 'pcall() without args: bad status')
 test:like(err, 'value expected', 'pcall() without args: error message')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-819-fix-missing-uclo.test.lua b/test/tarantool-tests/lj-819-fix-missing-uclo.test.lua
index 942c22b2..e2352c92 100644
--- a/test/tarantool-tests/lj-819-fix-missing-uclo.test.lua
+++ b/test/tarantool-tests/lj-819-fix-missing-uclo.test.lua
@@ -112,4 +112,4 @@ local _
 _, res = pcall(f)
 test:ok(type(res) == 'function', 'consistency on compilation: type of returned value is correct')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-864-varg-rec-base-offset.test.lua b/test/tarantool-tests/lj-864-varg-rec-base-offset.test.lua
index d41e33ff..02864e44 100644
--- a/test/tarantool-tests/lj-864-varg-rec-base-offset.test.lua
+++ b/test/tarantool-tests/lj-864-varg-rec-base-offset.test.lua
@@ -24,4 +24,4 @@ end
 -- due to failing assertion guard for type of loaded vararg slot.
 test:ok(test_rec_varg(42, 0), 'correct BC_VARG recording')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-906-fix-err-mem.test.lua b/test/tarantool-tests/lj-906-fix-err-mem.test.lua
index 6c6df338..7235e829 100644
--- a/test/tarantool-tests/lj-906-fix-err-mem.test.lua
+++ b/test/tarantool-tests/lj-906-fix-err-mem.test.lua
@@ -100,4 +100,4 @@ collectgarbage()
 
 test:ok(true, 'correctly throw memory error')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-981-folding-0.test.lua b/test/tarantool-tests/lj-981-folding-0.test.lua
index d156f53d..608cb2cd 100644
--- a/test/tarantool-tests/lj-981-folding-0.test.lua
+++ b/test/tarantool-tests/lj-981-folding-0.test.lua
@@ -60,4 +60,4 @@ test:ok(result == expected, 'TDUP and -0 folding')
 -- Test that there is no NEWREF -0 IR.
 test:ok(not traces[1]:has_ir('NEWREF.*-0'), '-0 is canonized for TDUP tab')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-994-instable-types-during-loop-unroll.test.lua b/test/tarantool-tests/lj-994-instable-types-during-loop-unroll.test.lua
index 78c04f21..730b0e61 100644
--- a/test/tarantool-tests/lj-994-instable-types-during-loop-unroll.test.lua
+++ b/test/tarantool-tests/lj-994-instable-types-during-loop-unroll.test.lua
@@ -50,4 +50,4 @@ end
 test:is(result, true, 'TDUP load forwarding was successful')
 ]]
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-flush-on-trace.test.lua b/test/tarantool-tests/lj-flush-on-trace.test.lua
index fe740087..a64fac4d 100644
--- a/test/tarantool-tests/lj-flush-on-trace.test.lua
+++ b/test/tarantool-tests/lj-flush-on-trace.test.lua
@@ -59,4 +59,4 @@ for _, subtest in pairs(cases) do
   test[subtest.test](test, output, subtest.expected, subtest.message)
 end
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/math-modf.test.lua b/test/tarantool-tests/math-modf.test.lua
index d8421db9..20a3bb16 100644
--- a/test/tarantool-tests/math-modf.test.lua
+++ b/test/tarantool-tests/math-modf.test.lua
@@ -32,3 +32,5 @@ for i = 1, 3 do
 end
 
 test:ok(array_is_consistent(r1) and array_is_consistent(r2), 'wrong modf')
+
+test:done(true)
diff --git a/test/tarantool-tests/misclib-getmetrics-lapi.test.lua b/test/tarantool-tests/misclib-getmetrics-lapi.test.lua
index 0ee71499..741900b6 100644
--- a/test/tarantool-tests/misclib-getmetrics-lapi.test.lua
+++ b/test/tarantool-tests/misclib-getmetrics-lapi.test.lua
@@ -430,4 +430,4 @@ test:test("tracenum-base", function(subtest)
     subtest:is(metrics.jit_trace_num, 0)
 end)
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/misclib-memprof-lapi.test.lua b/test/tarantool-tests/misclib-memprof-lapi.test.lua
index eae20893..3cb5c8be 100644
--- a/test/tarantool-tests/misclib-memprof-lapi.test.lua
+++ b/test/tarantool-tests/misclib-memprof-lapi.test.lua
@@ -296,4 +296,4 @@ test:test("jit-output", function(subtest)
   jit.opt.start(unpack(jit_opt_default))
 end)
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/misclib-sysprof-lapi.test.lua b/test/tarantool-tests/misclib-sysprof-lapi.test.lua
index 2f0635db..fdaed46a 100644
--- a/test/tarantool-tests/misclib-sysprof-lapi.test.lua
+++ b/test/tarantool-tests/misclib-sysprof-lapi.test.lua
@@ -129,4 +129,4 @@ check_mode("C", 100)
 
 os.remove(TMP_BINFILE)
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/or-144-gc64-asmref-l.test.lua b/test/tarantool-tests/or-144-gc64-asmref-l.test.lua
index 0c352c29..18c6efb2 100644
--- a/test/tarantool-tests/or-144-gc64-asmref-l.test.lua
+++ b/test/tarantool-tests/or-144-gc64-asmref-l.test.lua
@@ -25,4 +25,4 @@ end
 
 test:ok(global_env == getfenv(0), 'IR_LREF assembling correctness')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/or-232-unsink-64-kptr.test.lua b/test/tarantool-tests/or-232-unsink-64-kptr.test.lua
index fc8acaaf..4a0ece89 100644
--- a/test/tarantool-tests/or-232-unsink-64-kptr.test.lua
+++ b/test/tarantool-tests/or-232-unsink-64-kptr.test.lua
@@ -41,4 +41,4 @@ for i = 1, 1000 do
 end
 test:ok(true, "allocation is unsunk at the trace exit (no platform failures)")
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/or-94-arm64-ir-ahuvload-bool.test.lua b/test/tarantool-tests/or-94-arm64-ir-ahuvload-bool.test.lua
index 5418a058..990a3989 100644
--- a/test/tarantool-tests/or-94-arm64-ir-ahuvload-bool.test.lua
+++ b/test/tarantool-tests/or-94-arm64-ir-ahuvload-bool.test.lua
@@ -145,4 +145,4 @@ for i = 1, N_TESTS do
   jit.flush()
 end
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/tap.lua b/test/tarantool-tests/tap.lua
index 47a8fe87..8559ee52 100644
--- a/test/tarantool-tests/tap.lua
+++ b/test/tarantool-tests/tap.lua
@@ -10,7 +10,7 @@ local NULL = ffi.new("void *")
 local function finalize(test)
   -- TODO: implement finalization for subtests too.
   assert(test.parent == nil, 'FIXME: There is no way to use finalize subtest')
-  os.exit(test:check() and 0 or 1)
+  test:done(true)
 end
 
 local function indent(level, size)
@@ -337,12 +337,24 @@ local function skipcond(test, conditions)
   return test
 end
 
+local function done(test, exit)
+  if exit then
+    -- XXX: The second argument is required to properly close Lua
+    -- universe (i.e. invoke <lua_close> before exiting).
+    -- XXX: return is added explicitly to force CALLT emitting.
+    return os.exit(test:check() and 0 or 1, true)
+  else
+    assert(test:check(), 'Test check failed')
+  end
+end
+
 test_mt = {
   __index = {
     test       = new,
     plan       = plan,
     check      = check,
     diag       = diag,
+    done       = done,
     ok         = ok,
     fail       = fail,
     skip       = skip,
diff --git a/test/tarantool-tests/tonumber-negative-non-decimal-base.test.lua b/test/tarantool-tests/tonumber-negative-non-decimal-base.test.lua
index 94df3b1f..c7ac6b6f 100644
--- a/test/tarantool-tests/tonumber-negative-non-decimal-base.test.lua
+++ b/test/tarantool-tests/tonumber-negative-non-decimal-base.test.lua
@@ -26,4 +26,4 @@ test:ok(tonumber('- 1010  ', 2) == nil, 'space between sign and value')
 test:ok(tonumber('-_1010  ', 2) == nil,
 	'invalid character between sign and value')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/tools-utils-avl.test.lua b/test/tarantool-tests/tools-utils-avl.test.lua
index ebcfac2e..d7aa5011 100644
--- a/test/tarantool-tests/tools-utils-avl.test.lua
+++ b/test/tarantool-tests/tools-utils-avl.test.lua
@@ -38,4 +38,4 @@ test:is(avl.floor(root, -10), nil)
 -- Not exact upper bound.
 test:is(avl.floor(root, 2.75), 2)
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/unit-jit-parse.test.lua b/test/tarantool-tests/unit-jit-parse.test.lua
index 24216e87..2e6a2228 100644
--- a/test/tarantool-tests/unit-jit-parse.test.lua
+++ b/test/tarantool-tests/unit-jit-parse.test.lua
@@ -42,4 +42,4 @@ for irnum = 1, N_TESTS do
   test:ok(irref, 'find IR refernce by pattern: ' .. ir_pattern)
 end
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
-- 
2.30.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Tarantool-patches] [PATCH luajit v2 4/5] build: introduce LUAJIT_USE_ASAN option
  2023-07-21  8:12 [Tarantool-patches] [PATCH luajit v2 0/5] Add ASan support in LuaJIT Igor Munkin via Tarantool-patches
                   ` (2 preceding siblings ...)
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 3/5] test: introduce test:done TAP helper Igor Munkin via Tarantool-patches
@ 2023-07-21  8:12 ` Igor Munkin via Tarantool-patches
  2023-07-24 11:41   ` Sergey Bronnikov via Tarantool-patches
                     ` (2 more replies)
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 5/5] ci: introduce testing workflow with sanitizers Igor Munkin via Tarantool-patches
  2023-08-03  7:31 ` [Tarantool-patches] [PATCH luajit v2 0/5] Add ASan support in LuaJIT Igor Munkin via Tarantool-patches
  5 siblings, 3 replies; 25+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2023-07-21  8:12 UTC (permalink / raw)
  To: Sergey Kaplun, Sergey Bronnikov; +Cc: tarantool-patches

There was neither a special option nor a variable to configure the
sanitizers support via the build system since the commit
052c1a32a5e74b337686eee229d089d576775931 ("Add preliminary ASAN
support") where ASan support had been introduced. We finally decided to
use this feature in LuaJIT CI, so for convenient build configuration
LUAJIT_USE_ASAN option is added to the root CMakeLists.txt.

Resolves tarantool/tarantool#5878

Co-authored-by: Sergey Kaplun <skaplun@tarantool.org>
Signed-off-by: Igor Munkin <imun@tarantool.org>
---
 CMakeLists.txt | 33 ++++++++++++++++++++++++---------
 1 file changed, 24 insertions(+), 9 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6ef24bba..c4664cf9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -269,15 +269,30 @@ if(LUA_USE_ASSERT)
   AppendFlags(TARGET_C_FLAGS -DLUA_USE_ASSERT)
 endif()
 
-# TODO: Implement a configuration option to enable ASAN.
-# There are two entries of LUAJIT_USE_ASAN define:
-# $ grep -rnF 'LUAJIT_USE_ASAN' .
-# ./src/lj_str.c:15:#if LUAJIT_USE_ASAN
-# ./src/host/buildvm.c:36:#if LUAJIT_USE_ASAN
-# At the same time this flag is not provided by LuaJIT original
-# build system (i.e. src/Makefile.original) so there are no
-# related compiler and linker flags passed. This should be done
-# the right way later.
+# Turn on AddressSanitizer support. As a result, all artefacts
+# (i.e. buildvm, LuaJIT, testing infrastructure) are built with
+# ASan enabled.
+option(LUAJIT_USE_ASAN "Build LuaJIT with AddressSanitizer" OFF)
+if(LUAJIT_USE_ASAN)
+  if(NOT LUAJIT_USE_SYSMALLOC)
+    message(WARNING
+      "Unfortunately, internal LuaJIT memory allocator is not instrumented yet,"
+      " so to find any memory errors it's better to build LuaJIT with system"
+      " provided memory allocator (i.e. run CMake configuration phase with"
+      " -DLUAJIT_USE_SYSMALLOC=ON)."
+    )
+  endif()
+  # Use all recomendations described in AddressSanitize docs:
+  # https://clang.llvm.org/docs/AddressSanitizer.html.
+  AppendFlags(CMAKE_C_FLAGS
+    # Enable hints for AddressSanitizer (see src/lj_str.c).
+    -DLUAJIT_USE_ASAN
+    # XXX: To get nicer stack traces in error messages.
+    -fno-omit-frame-pointer
+    # Enable AddressSanitizer support.
+    -fsanitize=address
+  )
+endif()
 
 # --- Main source tree ---------------------------------------------------------
 
-- 
2.30.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [Tarantool-patches] [PATCH luajit v2 5/5] ci: introduce testing workflow with sanitizers
  2023-07-21  8:12 [Tarantool-patches] [PATCH luajit v2 0/5] Add ASan support in LuaJIT Igor Munkin via Tarantool-patches
                   ` (3 preceding siblings ...)
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 4/5] build: introduce LUAJIT_USE_ASAN option Igor Munkin via Tarantool-patches
@ 2023-07-21  8:12 ` Igor Munkin via Tarantool-patches
  2023-07-24 11:54   ` Sergey Bronnikov via Tarantool-patches
  2023-07-26 11:29   ` Sergey Kaplun via Tarantool-patches
  2023-08-03  7:31 ` [Tarantool-patches] [PATCH luajit v2 0/5] Add ASan support in LuaJIT Igor Munkin via Tarantool-patches
  5 siblings, 2 replies; 25+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2023-07-21  8:12 UTC (permalink / raw)
  To: Sergey Kaplun, Sergey Bronnikov; +Cc: tarantool-patches

This commit adds GitHub workflow running all available LuaJIT tests with
LUAJIT_USE_ASAN option enabled. For now, sanitizers workflow works only
for Linux/x86_64 as the most scaling setup in our CI. I believe we will
be able to add other platforms being supported, when macOS runners
starvation is defeated. There is also a separate GitHub Action
introduced for convenient setup of the environment.

Besided, internal LuaJIT memory allocator is not instrumented yet
unfortunately, so to find any memory faults it's better to build LuaJIT
with system provided memory allocator (i.e. run CMake configuration
phase with -DLUAJIT_USE_SYSMALLOC=ON). However, LUAJIT_USE_SYSMALLOC
cannot be enabled on x64 without GC64, since realloc usually doesn't
return addresses in the right address range. For more info, see root
CMakeLists.txt.

Follows up tarantool/tarantool#5878

Signed-off-by: Igor Munkin <imun@tarantool.org>
---
 .github/actions/setup-sanitizers/README.md  | 12 +++
 .github/actions/setup-sanitizers/action.yml | 24 ++++++
 .github/workflows/sanitizers-testing.yml    | 89 +++++++++++++++++++++
 3 files changed, 125 insertions(+)
 create mode 100644 .github/actions/setup-sanitizers/README.md
 create mode 100644 .github/actions/setup-sanitizers/action.yml
 create mode 100644 .github/workflows/sanitizers-testing.yml

diff --git a/.github/actions/setup-sanitizers/README.md b/.github/actions/setup-sanitizers/README.md
new file mode 100644
index 00000000..3aa9e214
--- /dev/null
+++ b/.github/actions/setup-sanitizers/README.md
@@ -0,0 +1,12 @@
+# Setup environment for sanitizers on Linux
+
+Action setups the environment on Linux runners (install requirements, setup the
+workflow environment, etc) for testing with sanitizers enabled.
+
+## How to use Github Action from Github workflow
+
+Add the following code to the running steps before LuaJIT configuration:
+```
+- uses: ./.github/actions/setup-sanitizers
+  if: ${{ matrix.OS == 'Linux' }}
+```
diff --git a/.github/actions/setup-sanitizers/action.yml b/.github/actions/setup-sanitizers/action.yml
new file mode 100644
index 00000000..ca6b6b9f
--- /dev/null
+++ b/.github/actions/setup-sanitizers/action.yml
@@ -0,0 +1,24 @@
+name: Setup CI environment for testing with sanitizers on Linux
+description: Common part to tweak Linux CI runner environment for sanitizers
+runs:
+  using: composite
+  steps:
+    - name: Setup CI environment
+      uses: ./.github/actions/setup
+    - name: Set CMAKE_BUILD_PARALLEL_LEVEL
+      run: |
+        # Set CMAKE_BUILD_PARALLEL_LEVEL environment variable to
+        # limit the number of parallel jobs for build/test step.
+        NPROC=$(nproc)
+        echo CMAKE_BUILD_PARALLEL_LEVEL=$(($NPROC + 1)) | tee -a $GITHUB_ENV
+      shell: bash
+    - name: Install build and test dependencies
+      run: |
+        apt -y update
+        apt -y install clang-11 cmake ninja-build make perl
+      shell: bash
+    - name: Set Clang as a default toolchain
+      run: |
+        echo CC=clang-11 | tee -a $GITHUB_ENV
+        echo CXX=clang++-11 | tee -a $GITHUB_ENV
+      shell: bash
diff --git a/.github/workflows/sanitizers-testing.yml b/.github/workflows/sanitizers-testing.yml
new file mode 100644
index 00000000..6c345108
--- /dev/null
+++ b/.github/workflows/sanitizers-testing.yml
@@ -0,0 +1,89 @@
+name: Sanitizers testing
+
+on:
+  push:
+    branches-ignore:
+      - '**-notest'
+      - 'upstream-**'
+    tags-ignore:
+      - '**'
+
+concurrency:
+  # An update of a developer branch cancels the previously
+  # scheduled workflow run for this branch. However, the default
+  # branch, and long-term branch (tarantool/release/2.11,
+  # tarantool/release/2.10, etc) workflow runs are never canceled.
+  #
+  # We use a trick here: define the concurrency group as 'workflow
+  # run ID' + # 'workflow run attempt' because it is a unique
+  # combination for any run. So it effectively discards grouping.
+  #
+  # XXX: we cannot use `github.sha` as a unique identifier because
+  # pushing a tag may cancel a run that works on a branch push
+  # event.
+  group: ${{ startsWith(github.ref, 'refs/heads/tarantool/')
+    && format('{0}-{1}', github.run_id, github.run_attempt)
+    || format('{0}-{1}', github.workflow, github.ref) }}
+  cancel-in-progress: true
+
+jobs:
+  test-asan:
+    strategy:
+      fail-fast: false
+      matrix:
+        # XXX: Let's start with only Linux/x86_64
+        BUILDTYPE: [Debug, Release]
+        include:
+          - BUILDTYPE: Debug
+            CMAKEFLAGS: -DCMAKE_BUILD_TYPE=Debug -DLUA_USE_ASSERT=ON -DLUA_USE_APICHECK=ON
+          - BUILDTYPE: Release
+            CMAKEFLAGS: -DCMAKE_BUILD_TYPE=RelWithDebInfo
+    runs-on: [self-hosted, regular, Linux, x86_64]
+    name: >
+      LuaJIT with ASan (Linux/x86_64)
+      ${{ matrix.BUILDTYPE }}
+      GC64:ON SYSMALLOC:ON
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+          submodules: recursive
+      - name: setup Linux for sanitizers
+        uses: ./.github/actions/setup-sanitizers
+      - name: configure
+        run: >
+          cmake -S . -B ${{ env.BUILDDIR }}
+          -G Ninja
+          ${{ matrix.CMAKEFLAGS }}
+          -DLUAJIT_USE_ASAN=ON
+          # XXX: Unfortunately, internal LuaJIT memory allocator
+          # is not instrumented yet, so to find any memory errors
+          # it's better to build LuaJIT with system provided
+          # memory allocator (i.e. run CMake configuration phase
+          # with -DLUAJIT_USE_SYSMALLOC=ON). For more info, see
+          # root CMakeLists.txt.
+          -DLUAJIT_USE_SYSMALLOC=ON
+          # XXX: LUAJIT_USE_SYSMALLOC cannot be enabled on x64
+          # without GC64, since realloc usually doesn't return
+          # addresses in the right address range. For more info,
+          # see root CMakeLists.txt.
+          -DLUAJIT_ENABLE_GC64=ON
+      - name: build
+        run: cmake --build . --parallel
+        working-directory: ${{ env.BUILDDIR }}
+      - name: test
+        env:
+          # Enable as much checks as possible. See more info here:
+          # https://github.com/google/sanitizers/wiki/AddressSanitizerFlags.
+          ASAN_OPTIONS: "                    \
+            detect_invalid_pointer_pairs=1:  \
+            detect_leaks=1:                  \
+            detect_stack_use_after_return=1: \
+            dump_instruction_bytes=1:        \
+            heap_profile=0:                  \
+            print_suppressions=0             \
+            symbolize=1:                     \
+            unmap_shadow_on_exit=1:          \
+          "
+        run: cmake --build . --parallel --target LuaJIT-test
+        working-directory: ${{ env.BUILDDIR }}
-- 
2.30.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 1/5] ci: clean up workflow for exotic builds
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 1/5] ci: clean up workflow for exotic builds Igor Munkin via Tarantool-patches
@ 2023-07-24 10:36   ` Sergey Bronnikov via Tarantool-patches
  2023-07-26  9:37   ` Sergey Kaplun via Tarantool-patches
  1 sibling, 0 replies; 25+ messages in thread
From: Sergey Bronnikov via Tarantool-patches @ 2023-07-24 10:36 UTC (permalink / raw)
  To: Igor Munkin, Sergey Kaplun; +Cc: tarantool-patches

Thanks for the patch! LGTM

On 7/21/23 11:12, Igor Munkin wrote:
> Unfortunately, the same mistake, that was introduced in the very first
> commit f877b7691d9eae73d64c63ee3770089569915459 ("ci: introduce GitHub
> Actions") and was fixed in the main testing pipeline in scope of the
> commit 524616a35c1267cb9ca260b8456b71dde1881e22 ("ci: remove GC64 matrix
> entries for ARM64 workflows"), was made in the new CI pipeline added in
> scope of the commit 32ac0cadcba58cd69058084c88100fdcc7b7dccf ("ci: add
> ARM64 architecture to exotic testing").
>
> Specifically, CMake option LUAJIT_ENABLE_GC64 changes nothing for ARM64
> LuaJIT builds (i.e. LJ_GC64 is defined on ARM64 platforms despite the
> value of LUAJIT_ENABLE_GC64). As a result GC64 entry is removed from
> all ARM64 flavors in exotic builds testing routine.
>
> Besides, all flavor labels are sorted alphabetically.
>
> Signed-off-by: Igor Munkin <imun@tarantool.org>
> ---
>   .github/workflows/exotic-builds-testing.yml | 4 +++-
>   1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/.github/workflows/exotic-builds-testing.yml b/.github/workflows/exotic-builds-testing.yml
> index 318fb4dd..7c57d238 100644
> --- a/.github/workflows/exotic-builds-testing.yml
> +++ b/.github/workflows/exotic-builds-testing.yml
> @@ -34,7 +34,7 @@ jobs:
>           BUILDTYPE: [Debug, Release]
>           ARCH: [ARM64, x86_64]
>           GC64: [ON, OFF]
> -        FLAVOR: [dualnum, checkhook, nojit, gdbjit]
> +        FLAVOR: [checkhook, dualnum, gdbjit, nojit]
>           include:
>             - BUILDTYPE: Debug
>               CMAKEFLAGS: -DCMAKE_BUILD_TYPE=Debug -DLUA_USE_ASSERT=ON -DLUA_USE_APICHECK=ON
> @@ -49,6 +49,8 @@ jobs:
>             - FLAVOR: gdbjit
>               FLAVORFLAGS: -DLUAJIT_USE_GDBJIT=ON
>           exclude:
> +          - ARCH: ARM64
> +            GC64: OFF
>             # DUALNUM is default for ARM64, no need for additional testing.
>             - FLAVOR: dualnum
>               ARCH: ARM64

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 2/5] memprof: remove invalid assertions
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 2/5] memprof: remove invalid assertions Igor Munkin via Tarantool-patches
@ 2023-07-24 10:46   ` Sergey Bronnikov via Tarantool-patches
  2023-07-26  9:41   ` Sergey Kaplun via Tarantool-patches
  1 sibling, 0 replies; 25+ messages in thread
From: Sergey Bronnikov via Tarantool-patches @ 2023-07-24 10:46 UTC (permalink / raw)
  To: Igor Munkin, Sergey Kaplun; +Cc: tarantool-patches

Thanks for the patch! LGTM

On 7/21/23 11:12, Igor Munkin wrote:
> The assertions checking the state of the allocator, being replaced by
> memory profiler, against NULL can fail if this allocator requires no
> internal state (e.g. glibc functions for allocating dynamic memory). In
> fact, when building LuaJIT with LUAJIT_USE_SYSMALLOC option enabled,
> NULL is given as the second parameter to <lua_newstate> and these
> assertions fail as a result. Hence, they are simply removed.
>
> Follows up tarantool/tarantool#5442
> Needed for tarantool/tarantool#5878
>
> Signed-off-by: Igor Munkin <imun@tarantool.org>
> ---
>   src/lj_memprof.c | 2 --
>   1 file changed, 2 deletions(-)
>
> diff --git a/src/lj_memprof.c b/src/lj_memprof.c
> index 8cab8204..c600c4f0 100644
> --- a/src/lj_memprof.c
> +++ b/src/lj_memprof.c
> @@ -295,7 +295,6 @@ int lj_memprof_start(struct lua_State *L, const struct lj_memprof_options *opt)
>     oalloc->allocf = lua_getallocf(L, &oalloc->state);
>     lua_assert(oalloc->allocf != NULL);
>     lua_assert(oalloc->allocf != memprof_allocf);
> -  lua_assert(oalloc->state != NULL);
>     lua_setallocf(L, memprof_allocf, oalloc->state);
>   
>     return PROFILE_SUCCESS;
> @@ -328,7 +327,6 @@ int lj_memprof_stop(struct lua_State *L)
>   
>     lua_assert(memprof_allocf == lua_getallocf(L, NULL));
>     lua_assert(oalloc->allocf != NULL);
> -  lua_assert(oalloc->state != NULL);
>     lua_setallocf(L, oalloc->allocf, oalloc->state);
>   
>     if (LJ_UNLIKELY(lj_wbuf_test_flag(out, STREAM_STOP))) {

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 3/5] test: introduce test:done TAP helper
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 3/5] test: introduce test:done TAP helper Igor Munkin via Tarantool-patches
@ 2023-07-24 10:53   ` Sergey Bronnikov via Tarantool-patches
  2023-07-26 10:43   ` Sergey Kaplun via Tarantool-patches
  1 sibling, 0 replies; 25+ messages in thread
From: Sergey Bronnikov via Tarantool-patches @ 2023-07-24 10:53 UTC (permalink / raw)
  To: Igor Munkin, Sergey Kaplun; +Cc: tarantool-patches

Thanks for the patch! LGTM

On 7/21/23 11:12, Igor Munkin wrote:
> Before the patch all tests (except <lj-603-err-snap-restore.test.lua>)
> in tarantool-tests suite terminate their execution via <os.exit> with
> the status depending on the test results. However, the second argument
> of <os.exit> was omitted and Lua universe was not properly finalized as
> a result. This behaviour becomes a problem, when LuaJIT is build with
> LUAJIT_USE_SYSMALLOC option and AddressSanitizer support enabled, since
> the sanitizer starts reporting false positive errors about the memory
> allocations without the corresponding memory releases. To resolve these
> errors, the second parameter to each <os.exit> call terminating the test
> has to be added.
>
> To avoid loss of the aforementioned parameter in future, <test:done>
> helper has been added to the TAP module. Depending on the single
> parameter, the new helper either properly finalize the test being run,
> or simply checks all the test assertions and raises an error if any of
> them fail. The latter case is added especially to handle the specifics
> of <lj-603-err-snap-restore.test.lua> and still check that everything
> works fine.
>
> Needed for tarantool/tarantool#5878
>
> Signed-off-by: Igor Munkin <imun@tarantool.org>
> ---
>   .../arm64-ccall-fp-convention.test.lua            |  2 +-
>   test/tarantool-tests/bc-jit-unpatching.test.lua   |  2 +-
>   .../c-library-path-length.test.lua                |  2 +-
>   .../fix-bit-shift-generation.test.lua             |  2 +-
>   test/tarantool-tests/fix-cdata-concat.test.lua    |  2 +-
>   test/tarantool-tests/fix-emit-rma.test.lua        |  2 +-
>   .../fix-fold-simplify-conv-sext.test.lua          |  2 +-
>   test/tarantool-tests/fix-gc-setupvalue.test.lua   |  2 +-
>   .../fix-slot-check-for-mm-record.test.lua         |  2 +-
>   .../gh-3196-incorrect-string-length.test.lua      |  2 +-
>   test/tarantool-tests/gh-4199-gc64-fuse.test.lua   |  2 +-
>   .../tarantool-tests/gh-4427-ffi-sandwich.test.lua |  2 +-
>   .../gh-4476-fix-string-find-recording.test.lua    |  2 +-
>   .../gh-4773-tonumber-fail-on-NUL-char.test.lua    |  2 +-
>   .../gh-5813-resolving-of-c-symbols.test.lua       |  2 +-
>   .../gh-6065-jit-library-smoke-tests.test.lua      |  2 +-
>   ...6084-missed-carg1-in-bctsetr-fallback.test.lua |  2 +-
>   .../gh-6096-external-unwinding-on-arm64.test.lua  |  2 +-
>   ...-6098-fix-side-exit-patching-on-arm64.test.lua |  2 +-
>   test/tarantool-tests/gh-6163-min-max.test.lua     |  2 +-
>   test/tarantool-tests/gh-6189-cur_L.test.lua       |  2 +-
>   ...27-bytecode-allocator-for-comparisons.test.lua |  2 +-
>   .../gh-6371-string-char-no-arg.test.lua           |  2 +-
>   .../gh-6782-stitching-in-vmevent-handler.test.lua |  2 +-
>   .../gh-6976-narrowing-of-unary-minus.test.lua     |  2 +-
>   ...-7264-add-proto-trace-sysprof-default.test.lua |  2 +-
>   .../tarantool-tests/gh-7745-oom-on-trace.test.lua |  2 +-
>   .../lj-350-sload-typecheck.test.lua               |  2 +-
>   .../lj-351-print-tostring-number.test.lua         |  2 +-
>   .../lj-356-ir-khash-non-string-obj.test.lua       |  2 +-
>   test/tarantool-tests/lj-357-arm64-hrefk.test.lua  |  2 +-
>   .../lj-366-strtab-correct-size.test.lua           |  2 +-
>   .../lj-375-ir-bufput-signed-char.test.lua         |  2 +-
>   .../lj-378-string-format-c-null-char.test.lua     |  2 +-
>   .../lj-408-tonumber-cdata-record.test.lua         |  2 +-
>   .../lj-416-xor-before-jcc.test.lua                |  2 +-
>   .../lj-418-assert-any-type.test.lua               |  2 +-
>   ...j-426-arm64-incorrect-check-closed-uv.test.lua |  2 +-
>   test/tarantool-tests/lj-430-maxirconst.test.lua   |  2 +-
>   ...-438-arm64-constant-rematerialization.test.lua |  2 +-
>   .../lj-445-fix-memory-probing-allocator.test.lua  |  2 +-
>   test/tarantool-tests/lj-463-os-date-oom.test.lua  |  2 +-
>   .../lj-494-table-chain-infinite-loop.test.lua     |  2 +-
>   .../lj-505-fold-no-strref-for-ptrdiff.test.lua    |  2 +-
>   .../lj-512-profiler-hook-finalizers.test.lua      |  2 +-
>   .../lj-524-fold-conv-respect-src-irt.test.lua     |  2 +-
>   test/tarantool-tests/lj-528-tonumber-0.test.lua   |  2 +-
>   .../lj-556-fix-loop-realignment.test.lua          |  2 +-
>   .../lj-574-overflow-unpack.test.lua               |  2 +-
>   .../lj-584-bad-renames-for-sunk-values.test.lua   |  2 +-
>   .../lj-586-debug-non-string-error.test.lua        |  2 +-
>   .../lj-601-fix-gc-finderrfunc.test.lua            |  2 +-
>   .../lj-603-err-snap-restore.test.lua              | 15 ++++++++-------
>   .../lj-671-arm64-assert-after-mremap.test.lua     |  2 +-
>   .../lj-672-cdata-allocation-recording.test.lua    |  2 +-
>   .../lj-688-snap-ir-rename.test.lua                |  2 +-
>   .../lj-695-ffi-vararg-call.test.lua               |  2 +-
>   .../lj-698-arm-pcall-panic.test.lua               |  2 +-
>   .../lj-704-bc-varg-use-def.test.lua               |  2 +-
>   .../lj-726-profile-flush-close.test.lua           |  2 +-
>   .../lj-727-lightuserdata-itern.test.lua           |  2 +-
>   .../lj-735-io-close-on-closed-file.test.lua       |  2 +-
>   test/tarantool-tests/lj-762-pcall-no-arg.test.lua |  2 +-
>   .../lj-819-fix-missing-uclo.test.lua              |  2 +-
>   .../lj-864-varg-rec-base-offset.test.lua          |  2 +-
>   test/tarantool-tests/lj-906-fix-err-mem.test.lua  |  2 +-
>   test/tarantool-tests/lj-981-folding-0.test.lua    |  2 +-
>   ...994-instable-types-during-loop-unroll.test.lua |  2 +-
>   test/tarantool-tests/lj-flush-on-trace.test.lua   |  2 +-
>   test/tarantool-tests/math-modf.test.lua           |  2 ++
>   .../misclib-getmetrics-lapi.test.lua              |  2 +-
>   .../tarantool-tests/misclib-memprof-lapi.test.lua |  2 +-
>   .../tarantool-tests/misclib-sysprof-lapi.test.lua |  2 +-
>   .../tarantool-tests/or-144-gc64-asmref-l.test.lua |  2 +-
>   .../or-232-unsink-64-kptr.test.lua                |  2 +-
>   .../or-94-arm64-ir-ahuvload-bool.test.lua         |  2 +-
>   test/tarantool-tests/tap.lua                      | 14 +++++++++++++-
>   .../tonumber-negative-non-decimal-base.test.lua   |  2 +-
>   test/tarantool-tests/tools-utils-avl.test.lua     |  2 +-
>   test/tarantool-tests/unit-jit-parse.test.lua      |  2 +-
>   80 files changed, 100 insertions(+), 85 deletions(-)
>
> diff --git a/test/tarantool-tests/arm64-ccall-fp-convention.test.lua b/test/tarantool-tests/arm64-ccall-fp-convention.test.lua
> index 8307e8b1..c58ba697 100644
> --- a/test/tarantool-tests/arm64-ccall-fp-convention.test.lua
> +++ b/test/tarantool-tests/arm64-ccall-fp-convention.test.lua
> @@ -62,4 +62,4 @@ test:ok(assert_sz12(sz12_222, {2, 2, 2}), '2 structures as args')
>   local sz12_333 = ffi_ccall.sum3sz12(sz12_111, sz12_111, sz12_111)
>   test:ok(assert_sz12(sz12_333, {3, 3, 3}), '3 structures as args')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/bc-jit-unpatching.test.lua b/test/tarantool-tests/bc-jit-unpatching.test.lua
> index f4f148c9..752fafac 100644
> --- a/test/tarantool-tests/bc-jit-unpatching.test.lua
> +++ b/test/tarantool-tests/bc-jit-unpatching.test.lua
> @@ -22,4 +22,4 @@ f(5)
>   test:ok(utils.frontend.hasbc(load(string.dump(f)), ret1bc),
>           'bytecode unpatching is OK')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/c-library-path-length.test.lua b/test/tarantool-tests/c-library-path-length.test.lua
> index 4f1e6602..63f3b695 100644
> --- a/test/tarantool-tests/c-library-path-length.test.lua
> +++ b/test/tarantool-tests/c-library-path-length.test.lua
> @@ -11,4 +11,4 @@ local res, err = package.loadlib(long_path, 'func')
>   test:ok(res == nil, 'loaded library with a too large path')
>   test:like(err, 'path too long', 'incorrect error')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/fix-bit-shift-generation.test.lua b/test/tarantool-tests/fix-bit-shift-generation.test.lua
> index d8e8a9b4..9704f32c 100644
> --- a/test/tarantool-tests/fix-bit-shift-generation.test.lua
> +++ b/test/tarantool-tests/fix-bit-shift-generation.test.lua
> @@ -44,4 +44,4 @@ for i = 1, NTESTS do
>     test:ok(result[i] == shl(1ULL, i + 32), 'valid rol')
>   end
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/fix-cdata-concat.test.lua b/test/tarantool-tests/fix-cdata-concat.test.lua
> index df069e58..2ea37b02 100644
> --- a/test/tarantool-tests/fix-cdata-concat.test.lua
> +++ b/test/tarantool-tests/fix-cdata-concat.test.lua
> @@ -18,4 +18,4 @@ debug.getmetatable(1LL).__concat = function(a, b)
>   end
>   test:ok(1LL .. 2LL == '1LL2LL', 'cdata concatenation with defined metamethod')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/fix-emit-rma.test.lua b/test/tarantool-tests/fix-emit-rma.test.lua
> index 1f8e66f4..42804447 100644
> --- a/test/tarantool-tests/fix-emit-rma.test.lua
> +++ b/test/tarantool-tests/fix-emit-rma.test.lua
> @@ -101,4 +101,4 @@ end
>   -- trace.
>   test:ok(true, 'IR_OBAR emit_rma check correctness')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/fix-fold-simplify-conv-sext.test.lua b/test/tarantool-tests/fix-fold-simplify-conv-sext.test.lua
> index 60eb3e7c..d5356816 100644
> --- a/test/tarantool-tests/fix-fold-simplify-conv-sext.test.lua
> +++ b/test/tarantool-tests/fix-fold-simplify-conv-sext.test.lua
> @@ -32,4 +32,4 @@ for i = 1, NTEST do
>     test:ok(results[i] == expected[i], 'correct cdata indexing')
>   end
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/fix-gc-setupvalue.test.lua b/test/tarantool-tests/fix-gc-setupvalue.test.lua
> index 21acc9bf..6b57283f 100644
> --- a/test/tarantool-tests/fix-gc-setupvalue.test.lua
> +++ b/test/tarantool-tests/fix-gc-setupvalue.test.lua
> @@ -58,4 +58,4 @@ for i = 1, 1e2 do local _ = {string.rep('0', i)} end
>   
>   test:ok(_G.parent() == 42, 'correct set up of upvalue')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua b/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua
> index 6161747f..602426ac 100644
> --- a/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua
> +++ b/test/tarantool-tests/fix-slot-check-for-mm-record.test.lua
> @@ -79,4 +79,4 @@ end
>   jit.opt.start('hotloop=1', 'maxrecord=2048')
>   
>   test:ok(try(require('ffi').abi('gc64')))
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-3196-incorrect-string-length.test.lua b/test/tarantool-tests/gh-3196-incorrect-string-length.test.lua
> index 0342c832..b82029f6 100644
> --- a/test/tarantool-tests/gh-3196-incorrect-string-length.test.lua
> +++ b/test/tarantool-tests/gh-3196-incorrect-string-length.test.lua
> @@ -12,4 +12,4 @@ test:is(h:len(), 20)
>   h = "\x0F\x93\xE2\x1C\xCA\xDE\x28\x08\x26\x01\xED\x0A\x2F\xE4\x21\x02\x97\x77\xD9\x3E"
>   test:is(h:len(), 20)
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-4199-gc64-fuse.test.lua b/test/tarantool-tests/gh-4199-gc64-fuse.test.lua
> index 4513d43b..ca050cf0 100644
> --- a/test/tarantool-tests/gh-4199-gc64-fuse.test.lua
> +++ b/test/tarantool-tests/gh-4199-gc64-fuse.test.lua
> @@ -83,4 +83,4 @@ for n = 1, 100 do
>   end
>   
>   test:ok(ok, 'IR constant fusion')
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-4427-ffi-sandwich.test.lua b/test/tarantool-tests/gh-4427-ffi-sandwich.test.lua
> index 677a6085..34139d86 100644
> --- a/test/tarantool-tests/gh-4427-ffi-sandwich.test.lua
> +++ b/test/tarantool-tests/gh-4427-ffi-sandwich.test.lua
> @@ -59,4 +59,4 @@ for _, subtest in pairs(cases) do
>     test[subtest.test](test, output, subtest.expected, subtest.message)
>   end
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-4476-fix-string-find-recording.test.lua b/test/tarantool-tests/gh-4476-fix-string-find-recording.test.lua
> index 56776192..c4acdd3d 100644
> --- a/test/tarantool-tests/gh-4476-fix-string-find-recording.test.lua
> +++ b/test/tarantool-tests/gh-4476-fix-string-find-recording.test.lua
> @@ -76,4 +76,4 @@ until not e
>   
>   test:is(count_vm, count_jit)
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-4773-tonumber-fail-on-NUL-char.test.lua b/test/tarantool-tests/gh-4773-tonumber-fail-on-NUL-char.test.lua
> index 112c491e..7bacc0f9 100644
> --- a/test/tarantool-tests/gh-4773-tonumber-fail-on-NUL-char.test.lua
> +++ b/test/tarantool-tests/gh-4773-tonumber-fail-on-NUL-char.test.lua
> @@ -19,4 +19,4 @@ test:is(tonumber(t.zero), 0)
>   test:is(tonumber(t.zero .. t.tail), nil)
>   test:is(tonumber(t.zero .. t.null .. t.tail), nil)
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-5813-resolving-of-c-symbols.test.lua b/test/tarantool-tests/gh-5813-resolving-of-c-symbols.test.lua
> index 1209d288..30b8a3ca 100644
> --- a/test/tarantool-tests/gh-5813-resolving-of-c-symbols.test.lua
> +++ b/test/tarantool-tests/gh-5813-resolving-of-c-symbols.test.lua
> @@ -95,4 +95,4 @@ test:ok(tree_contains(symbols.cfunc, "allocate_string"))
>   -- perform a test in that case, since it is impossible to load Lua module
>   -- written in C if it doesn't have a .dynsym segment.
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-6065-jit-library-smoke-tests.test.lua b/test/tarantool-tests/gh-6065-jit-library-smoke-tests.test.lua
> index 5d7fd7e2..8105c3ba 100644
> --- a/test/tarantool-tests/gh-6065-jit-library-smoke-tests.test.lua
> +++ b/test/tarantool-tests/gh-6065-jit-library-smoke-tests.test.lua
> @@ -10,4 +10,4 @@ test:plan(1)
>   -- as a second argument to the assertion.
>   test:ok(pcall(jit.on))
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-6084-missed-carg1-in-bctsetr-fallback.test.lua b/test/tarantool-tests/gh-6084-missed-carg1-in-bctsetr-fallback.test.lua
> index 10db7603..5cc9416a 100644
> --- a/test/tarantool-tests/gh-6084-missed-carg1-in-bctsetr-fallback.test.lua
> +++ b/test/tarantool-tests/gh-6084-missed-carg1-in-bctsetr-fallback.test.lua
> @@ -24,4 +24,4 @@ local res = table.move(t, 1, 1, 2)
>   test:ok(t == res, 'table.move returns the same table')
>   test:ok(t[1] == t[2], 'table.move is correct')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-6096-external-unwinding-on-arm64.test.lua b/test/tarantool-tests/gh-6096-external-unwinding-on-arm64.test.lua
> index cdeea441..097e771c 100644
> --- a/test/tarantool-tests/gh-6096-external-unwinding-on-arm64.test.lua
> +++ b/test/tarantool-tests/gh-6096-external-unwinding-on-arm64.test.lua
> @@ -10,4 +10,4 @@ test:plan(1)
>   local res = pcall(require, 'not-existing-module')
>   test:ok(res == false, 'successful unwinding in pcall')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-6098-fix-side-exit-patching-on-arm64.test.lua b/test/tarantool-tests/gh-6098-fix-side-exit-patching-on-arm64.test.lua
> index cfcc6adb..93db3041 100644
> --- a/test/tarantool-tests/gh-6098-fix-side-exit-patching-on-arm64.test.lua
> +++ b/test/tarantool-tests/gh-6098-fix-side-exit-patching-on-arm64.test.lua
> @@ -129,4 +129,4 @@ pxcall(cbool, false)
>   cbool(false)
>   
>   test:ok(true)
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-6163-min-max.test.lua b/test/tarantool-tests/gh-6163-min-max.test.lua
> index 882cb1a0..63437955 100644
> --- a/test/tarantool-tests/gh-6163-min-max.test.lua
> +++ b/test/tarantool-tests/gh-6163-min-max.test.lua
> @@ -262,4 +262,4 @@ end
>   -- expected: 1.1 1.1 1.1 1.1
>   test:ok(array_is_consistent(result), 'max: fold_kfold_numarith')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-6189-cur_L.test.lua b/test/tarantool-tests/gh-6189-cur_L.test.lua
> index a5096a7c..d6b8eef0 100644
> --- a/test/tarantool-tests/gh-6189-cur_L.test.lua
> +++ b/test/tarantool-tests/gh-6189-cur_L.test.lua
> @@ -28,4 +28,4 @@ assert(pcall(libcur_L.error_from_other_thread) == false, "return from error")
>   cbool(false)
>   
>   test:ok(true)
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-6227-bytecode-allocator-for-comparisons.test.lua b/test/tarantool-tests/gh-6227-bytecode-allocator-for-comparisons.test.lua
> index da399bcf..07152744 100644
> --- a/test/tarantool-tests/gh-6227-bytecode-allocator-for-comparisons.test.lua
> +++ b/test/tarantool-tests/gh-6227-bytecode-allocator-for-comparisons.test.lua
> @@ -54,4 +54,4 @@ for _ = 1, 3 do
>   end
>   
>   test:ok(true)
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-6371-string-char-no-arg.test.lua b/test/tarantool-tests/gh-6371-string-char-no-arg.test.lua
> index 90121860..48a5857d 100644
> --- a/test/tarantool-tests/gh-6371-string-char-no-arg.test.lua
> +++ b/test/tarantool-tests/gh-6371-string-char-no-arg.test.lua
> @@ -27,4 +27,4 @@ for i = 1, NTEST do
>     test:ok(results[i] == '', 'correct recording of string.char() without args')
>   end
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-6782-stitching-in-vmevent-handler.test.lua b/test/tarantool-tests/gh-6782-stitching-in-vmevent-handler.test.lua
> index 385e7648..afca6c40 100644
> --- a/test/tarantool-tests/gh-6782-stitching-in-vmevent-handler.test.lua
> +++ b/test/tarantool-tests/gh-6782-stitching-in-vmevent-handler.test.lua
> @@ -32,4 +32,4 @@ require('jit.bc').dump(loadstring(string.dump(fibb)), {
>   -- `jit.bc` functions inside.
>   test:ok(fibb(2) == 1, 'run compiled function inside vmevent handler')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-6976-narrowing-of-unary-minus.test.lua b/test/tarantool-tests/gh-6976-narrowing-of-unary-minus.test.lua
> index 40387cca..31890965 100644
> --- a/test/tarantool-tests/gh-6976-narrowing-of-unary-minus.test.lua
> +++ b/test/tarantool-tests/gh-6976-narrowing-of-unary-minus.test.lua
> @@ -48,4 +48,4 @@ test:ok(check(function()
>     return res
>   end), 'assertion guard fail')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-7264-add-proto-trace-sysprof-default.test.lua b/test/tarantool-tests/gh-7264-add-proto-trace-sysprof-default.test.lua
> index 9cce32cb..c1d68e3c 100644
> --- a/test/tarantool-tests/gh-7264-add-proto-trace-sysprof-default.test.lua
> +++ b/test/tarantool-tests/gh-7264-add-proto-trace-sysprof-default.test.lua
> @@ -44,4 +44,4 @@ assert(misc.sysprof.start({ mode = 'D' }))
>   allocate()
>   test:ok(misc.sysprof.stop(), 'trace record in sysprof runtime')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/gh-7745-oom-on-trace.test.lua b/test/tarantool-tests/gh-7745-oom-on-trace.test.lua
> index 81be445d..9ac41ac7 100644
> --- a/test/tarantool-tests/gh-7745-oom-on-trace.test.lua
> +++ b/test/tarantool-tests/gh-7745-oom-on-trace.test.lua
> @@ -38,4 +38,4 @@ collectgarbage()
>   
>   test:ok(res == false)
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-350-sload-typecheck.test.lua b/test/tarantool-tests/lj-350-sload-typecheck.test.lua
> index 5b25864d..33380170 100644
> --- a/test/tarantool-tests/lj-350-sload-typecheck.test.lua
> +++ b/test/tarantool-tests/lj-350-sload-typecheck.test.lua
> @@ -41,4 +41,4 @@ jit.off()
>   
>   test:ok(not traceinfo(2), 'the second trace should not be compiled')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-351-print-tostring-number.test.lua b/test/tarantool-tests/lj-351-print-tostring-number.test.lua
> index b7041f2a..c67c6859 100644
> --- a/test/tarantool-tests/lj-351-print-tostring-number.test.lua
> +++ b/test/tarantool-tests/lj-351-print-tostring-number.test.lua
> @@ -26,4 +26,4 @@ for _, subtest in pairs(cases) do
>             ('subtest is OK for %s type'):format(subtest.typename))
>   end
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-356-ir-khash-non-string-obj.test.lua b/test/tarantool-tests/lj-356-ir-khash-non-string-obj.test.lua
> index 9977205d..5159ac32 100644
> --- a/test/tarantool-tests/lj-356-ir-khash-non-string-obj.test.lua
> +++ b/test/tarantool-tests/lj-356-ir-khash-non-string-obj.test.lua
> @@ -90,4 +90,4 @@ for i = 1, N_ITERATIONS do
>     test:ok(result_tab[i] == MAGIC, 'correct hash lookup from the table')
>   end
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-357-arm64-hrefk.test.lua b/test/tarantool-tests/lj-357-arm64-hrefk.test.lua
> index d7e9c85e..8db8bbfc 100644
> --- a/test/tarantool-tests/lj-357-arm64-hrefk.test.lua
> +++ b/test/tarantool-tests/lj-357-arm64-hrefk.test.lua
> @@ -29,4 +29,4 @@ end
>   test:is(t.hrefk, -START)
>   test:is(t[t.hrefk], STOP)
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-366-strtab-correct-size.test.lua b/test/tarantool-tests/lj-366-strtab-correct-size.test.lua
> index aa4e72e7..8a97a441 100644
> --- a/test/tarantool-tests/lj-366-strtab-correct-size.test.lua
> +++ b/test/tarantool-tests/lj-366-strtab-correct-size.test.lua
> @@ -202,4 +202,4 @@ test:ok(sym_is_found == true, 'symbol is found')
>   local ret = os.remove(elf_filename)
>   assert(ret == true, 'cannot remove an object file')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-375-ir-bufput-signed-char.test.lua b/test/tarantool-tests/lj-375-ir-bufput-signed-char.test.lua
> index f600d898..9f913eba 100644
> --- a/test/tarantool-tests/lj-375-ir-bufput-signed-char.test.lua
> +++ b/test/tarantool-tests/lj-375-ir-bufput-signed-char.test.lua
> @@ -29,4 +29,4 @@ for i = 1, NTEST do
>     test:ok(results[i] == 0xff, 'correct 0xff signed char assembling')
>   end
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-378-string-format-c-null-char.test.lua b/test/tarantool-tests/lj-378-string-format-c-null-char.test.lua
> index 15cefadf..7632c7fd 100644
> --- a/test/tarantool-tests/lj-378-string-format-c-null-char.test.lua
> +++ b/test/tarantool-tests/lj-378-string-format-c-null-char.test.lua
> @@ -8,4 +8,4 @@ test:plan(1)
>   -- See also https://github.com/LuaJIT/LuaJIT/issues/378.
>   
>   test:is(string.format('%c', 0), '\0', 'string.format %c on null char')
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-408-tonumber-cdata-record.test.lua b/test/tarantool-tests/lj-408-tonumber-cdata-record.test.lua
> index bdd0aaaa..3a7e1f28 100644
> --- a/test/tarantool-tests/lj-408-tonumber-cdata-record.test.lua
> +++ b/test/tarantool-tests/lj-408-tonumber-cdata-record.test.lua
> @@ -41,4 +41,4 @@ check(0LL)
>   test:ok(check(0LL), 'recorded with 0LL and converted for 0LL')
>   test:ok(not check(NULL), 'recorded with 0LL and not converted for NULL')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-416-xor-before-jcc.test.lua b/test/tarantool-tests/lj-416-xor-before-jcc.test.lua
> index 861114e8..605bb92a 100644
> --- a/test/tarantool-tests/lj-416-xor-before-jcc.test.lua
> +++ b/test/tarantool-tests/lj-416-xor-before-jcc.test.lua
> @@ -97,4 +97,4 @@ for _ = 1, 3 do
>   end
>   test:ok(true, 'impossible branch is not taken')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-418-assert-any-type.test.lua b/test/tarantool-tests/lj-418-assert-any-type.test.lua
> index 24683554..51b21ed8 100644
> --- a/test/tarantool-tests/lj-418-assert-any-type.test.lua
> +++ b/test/tarantool-tests/lj-418-assert-any-type.test.lua
> @@ -15,4 +15,4 @@ xpcall(assert, function(obj)
>     test:ok(obj == retv, 'xpcall error handler function get non-string argument')
>   end, false, retv)
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-426-arm64-incorrect-check-closed-uv.test.lua b/test/tarantool-tests/lj-426-arm64-incorrect-check-closed-uv.test.lua
> index 4cdf1211..a689ed60 100644
> --- a/test/tarantool-tests/lj-426-arm64-incorrect-check-closed-uv.test.lua
> +++ b/test/tarantool-tests/lj-426-arm64-incorrect-check-closed-uv.test.lua
> @@ -36,4 +36,4 @@ while (misc.getmetrics().gc_steps_atomic == old_steps_atomic) do
>   end
>   
>   test:ok(true)
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-430-maxirconst.test.lua b/test/tarantool-tests/lj-430-maxirconst.test.lua
> index 531acd7d..903fad8e 100644
> --- a/test/tarantool-tests/lj-430-maxirconst.test.lua
> +++ b/test/tarantool-tests/lj-430-maxirconst.test.lua
> @@ -44,4 +44,4 @@ irconst4()
>   jit.off()
>   test:ok(not traceinfo(2), 'trace should not appear due to maxirconst limit')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-438-arm64-constant-rematerialization.test.lua b/test/tarantool-tests/lj-438-arm64-constant-rematerialization.test.lua
> index 0a59209c..9886fe09 100644
> --- a/test/tarantool-tests/lj-438-arm64-constant-rematerialization.test.lua
> +++ b/test/tarantool-tests/lj-438-arm64-constant-rematerialization.test.lua
> @@ -102,4 +102,4 @@ wrap()
>   
>   test:ok(true, 'the resulting trace is correct')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-445-fix-memory-probing-allocator.test.lua b/test/tarantool-tests/lj-445-fix-memory-probing-allocator.test.lua
> index a228651b..da924bb0 100644
> --- a/test/tarantool-tests/lj-445-fix-memory-probing-allocator.test.lua
> +++ b/test/tarantool-tests/lj-445-fix-memory-probing-allocator.test.lua
> @@ -47,4 +47,4 @@ for _ = 1, MAX_GB do
>     end
>   end
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-463-os-date-oom.test.lua b/test/tarantool-tests/lj-463-os-date-oom.test.lua
> index 0861ce14..e431d19d 100644
> --- a/test/tarantool-tests/lj-463-os-date-oom.test.lua
> +++ b/test/tarantool-tests/lj-463-os-date-oom.test.lua
> @@ -14,4 +14,4 @@ end
>   
>   test:ok(true, 'os.date() finished without OOM')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-494-table-chain-infinite-loop.test.lua b/test/tarantool-tests/lj-494-table-chain-infinite-loop.test.lua
> index aae90e8a..3dd17e7a 100644
> --- a/test/tarantool-tests/lj-494-table-chain-infinite-loop.test.lua
> +++ b/test/tarantool-tests/lj-494-table-chain-infinite-loop.test.lua
> @@ -174,4 +174,4 @@ for c, v in pairs(victims) do
>   end
>   test:ok(true, "table keys collisions are resolved properly (no assertions failed)")
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-505-fold-no-strref-for-ptrdiff.test.lua b/test/tarantool-tests/lj-505-fold-no-strref-for-ptrdiff.test.lua
> index fec08b30..a40e7796 100644
> --- a/test/tarantool-tests/lj-505-fold-no-strref-for-ptrdiff.test.lua
> +++ b/test/tarantool-tests/lj-505-fold-no-strref-for-ptrdiff.test.lua
> @@ -18,4 +18,4 @@ for _ = 1, 20 do
>   end
>   test:ok(true, "string.find offset aritmetics wasn't broken while recording")
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-512-profiler-hook-finalizers.test.lua b/test/tarantool-tests/lj-512-profiler-hook-finalizers.test.lua
> index f7ee344f..a282a10f 100644
> --- a/test/tarantool-tests/lj-512-profiler-hook-finalizers.test.lua
> +++ b/test/tarantool-tests/lj-512-profiler-hook-finalizers.test.lua
> @@ -28,4 +28,4 @@ profile.stop()
>   test:ok(nsamples >= 0.5 * (finish - start) * 1e3 / INTERVAL,
>           'profiler sampling')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-524-fold-conv-respect-src-irt.test.lua b/test/tarantool-tests/lj-524-fold-conv-respect-src-irt.test.lua
> index a13e5d55..70d330ac 100644
> --- a/test/tarantool-tests/lj-524-fold-conv-respect-src-irt.test.lua
> +++ b/test/tarantool-tests/lj-524-fold-conv-respect-src-irt.test.lua
> @@ -21,4 +21,4 @@ end
>   
>   test:is(tonumber(sq), math.fmod(math.pow(42, 8), math.pow(2, 32)))
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-528-tonumber-0.test.lua b/test/tarantool-tests/lj-528-tonumber-0.test.lua
> index 27f17e54..8b4c0832 100644
> --- a/test/tarantool-tests/lj-528-tonumber-0.test.lua
> +++ b/test/tarantool-tests/lj-528-tonumber-0.test.lua
> @@ -10,4 +10,4 @@ test:plan(1)
>   -- As numbers -0 equals to 0, so convert it back to string.
>   test:ok(tostring(tonumber('-0')) == '-0', 'correct "-0" string parsing')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-556-fix-loop-realignment.test.lua b/test/tarantool-tests/lj-556-fix-loop-realignment.test.lua
> index b94bd3e9..89f70693 100644
> --- a/test/tarantool-tests/lj-556-fix-loop-realignment.test.lua
> +++ b/test/tarantool-tests/lj-556-fix-loop-realignment.test.lua
> @@ -17,4 +17,4 @@ while s > 0 do
>   end
>   
>   test:ok(true, 'loop is compiled and ran successfully')
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-574-overflow-unpack.test.lua b/test/tarantool-tests/lj-574-overflow-unpack.test.lua
> index 6715d947..671ccddd 100644
> --- a/test/tarantool-tests/lj-574-overflow-unpack.test.lua
> +++ b/test/tarantool-tests/lj-574-overflow-unpack.test.lua
> @@ -9,4 +9,4 @@ test:plan(1)
>   local r, e = pcall(unpack, {}, 0, 2^31 - 1)
>   test:ok(not r and e == 'too many results to unpack', 'overflow check in unpack')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-584-bad-renames-for-sunk-values.test.lua b/test/tarantool-tests/lj-584-bad-renames-for-sunk-values.test.lua
> index e0c3e577..cb0623b1 100644
> --- a/test/tarantool-tests/lj-584-bad-renames-for-sunk-values.test.lua
> +++ b/test/tarantool-tests/lj-584-bad-renames-for-sunk-values.test.lua
> @@ -96,4 +96,4 @@ end, function()
>     test:fail('Invalid Lua stack has been restored')
>   end)
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-586-debug-non-string-error.test.lua b/test/tarantool-tests/lj-586-debug-non-string-error.test.lua
> index c00301a1..67869708 100644
> --- a/test/tarantool-tests/lj-586-debug-non-string-error.test.lua
> +++ b/test/tarantool-tests/lj-586-debug-non-string-error.test.lua
> @@ -44,4 +44,4 @@ EOF]]):format(luabin, magic)
>   
>   local res = io.popen(cmd):read('*all'):gsub('%s+$', '')
>   test:ok(res == expected, 'handle non-string error in debug.debug()')
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-601-fix-gc-finderrfunc.test.lua b/test/tarantool-tests/lj-601-fix-gc-finderrfunc.test.lua
> index 2122c7a0..1549257d 100644
> --- a/test/tarantool-tests/lj-601-fix-gc-finderrfunc.test.lua
> +++ b/test/tarantool-tests/lj-601-fix-gc-finderrfunc.test.lua
> @@ -35,4 +35,4 @@ a = nil
>   -- frame. As a result, error is raised in __gc metamethod above.
>   test:ok(mixcframe.test_handle_err(), 'error in __gc is successfully handled')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-603-err-snap-restore.test.lua b/test/tarantool-tests/lj-603-err-snap-restore.test.lua
> index a6c831ed..791107ba 100644
> --- a/test/tarantool-tests/lj-603-err-snap-restore.test.lua
> +++ b/test/tarantool-tests/lj-603-err-snap-restore.test.lua
> @@ -55,16 +55,17 @@ end
>   -- restoration from the snapshot.
>   if require('ffi').abi('gc64') then
>     -- luacheck: no unused
> -  local _, _, _, _, _, _
> +  local _, _, _, _, _
>     do_test()
>   else
>     -- luacheck: no unused
> -  local _, _, _, _
> +  local _, _, _, _, _, _, _, _, _, _, _, _, _
>     do_test()
>   end
>   
> --- XXX: Don't use `os.exit()` here by intention. When error on
> --- snap restoration is raised, `err_unwind()` doesn't stop on
> --- correct cframe. So later, on exit from VM this corrupted cframe
> --- chain shows itself. `os.exit()` literally calls `exit()` and
> --- doesn't show the issue.
> +-- XXX: Don't force `test:done()` finish test with `os.exit()` by
> +-- intention. When error on snapshot restoration is raised,
> +-- `err_unwind()` doesn't stop on the correct cframe. So later, on
> +-- exit from VM this corrupted cframe chain shows itself.
> +-- `os.exit()` just calls `exit()` and doesn't show the issue.
> +test:done(false)
> diff --git a/test/tarantool-tests/lj-671-arm64-assert-after-mremap.test.lua b/test/tarantool-tests/lj-671-arm64-assert-after-mremap.test.lua
> index 0558cbe3..74ade1db 100644
> --- a/test/tarantool-tests/lj-671-arm64-assert-after-mremap.test.lua
> +++ b/test/tarantool-tests/lj-671-arm64-assert-after-mremap.test.lua
> @@ -21,4 +21,4 @@ local DEFAULT_MMAP_THRESHOLD = 128 * 1024
>   local s = string.rep('x', DEFAULT_MMAP_THRESHOLD)..'x'
>   test:ok(s)
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-672-cdata-allocation-recording.test.lua b/test/tarantool-tests/lj-672-cdata-allocation-recording.test.lua
> index 1d6b19ba..22deac5d 100644
> --- a/test/tarantool-tests/lj-672-cdata-allocation-recording.test.lua
> +++ b/test/tarantool-tests/lj-672-cdata-allocation-recording.test.lua
> @@ -28,4 +28,4 @@ end
>   
>   test:ok(traceinfo(1), 'new trace created')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-688-snap-ir-rename.test.lua b/test/tarantool-tests/lj-688-snap-ir-rename.test.lua
> index 46bddd9f..807e0811 100644
> --- a/test/tarantool-tests/lj-688-snap-ir-rename.test.lua
> +++ b/test/tarantool-tests/lj-688-snap-ir-rename.test.lua
> @@ -57,4 +57,4 @@ end
>   test:ok(true, 'IR_RENAME is fine')
>   -- `test:check() and 0 or 1` is replaced with just test:check()
>   -- here, because otherwise, it affects the renaming process.
> -os.exit(test:check())
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-695-ffi-vararg-call.test.lua b/test/tarantool-tests/lj-695-ffi-vararg-call.test.lua
> index 04be1998..496a4c0d 100644
> --- a/test/tarantool-tests/lj-695-ffi-vararg-call.test.lua
> +++ b/test/tarantool-tests/lj-695-ffi-vararg-call.test.lua
> @@ -13,4 +13,4 @@ local result = ffi.string(str)
>   test:is(#result, strlen)
>   test:is(result, 'try vararg function: imun:9.00(9) - 18446744073709551615')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-698-arm-pcall-panic.test.lua b/test/tarantool-tests/lj-698-arm-pcall-panic.test.lua
> index 88476d3e..5f9d193a 100644
> --- a/test/tarantool-tests/lj-698-arm-pcall-panic.test.lua
> +++ b/test/tarantool-tests/lj-698-arm-pcall-panic.test.lua
> @@ -15,4 +15,4 @@ local runner = ffi.cast("int (*)(int, int, int, int, int, int, int, int, int)",
>   local st = pcall(runner, 1, 1, 1, 1, 1, 1, 1, 1, 1)
>   test:ok(not st, 'error handling completed correctly')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-704-bc-varg-use-def.test.lua b/test/tarantool-tests/lj-704-bc-varg-use-def.test.lua
> index e6a0973b..93455e3c 100644
> --- a/test/tarantool-tests/lj-704-bc-varg-use-def.test.lua
> +++ b/test/tarantool-tests/lj-704-bc-varg-use-def.test.lua
> @@ -90,4 +90,4 @@ wrap_ret_bc(ON_TRACE_VALUE)
>   
>   test:ok(result ~= 0, 'use-def analysis for FUNCV with jump before BC_VARG')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-726-profile-flush-close.test.lua b/test/tarantool-tests/lj-726-profile-flush-close.test.lua
> index a3f8def9..36cca43d 100644
> --- a/test/tarantool-tests/lj-726-profile-flush-close.test.lua
> +++ b/test/tarantool-tests/lj-726-profile-flush-close.test.lua
> @@ -26,4 +26,4 @@ test:ok(f:read(0), 'profile output was flushed and closed')
>   
>   assert(os.remove(TEST_FILE))
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-727-lightuserdata-itern.test.lua b/test/tarantool-tests/lj-727-lightuserdata-itern.test.lua
> index 3e459f43..bb01f122 100644
> --- a/test/tarantool-tests/lj-727-lightuserdata-itern.test.lua
> +++ b/test/tarantool-tests/lj-727-lightuserdata-itern.test.lua
> @@ -42,4 +42,4 @@ end)
>   test.strict = true
>   test:is_deeply(visited, t, 'userdata node is visited')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-735-io-close-on-closed-file.test.lua b/test/tarantool-tests/lj-735-io-close-on-closed-file.test.lua
> index 2a590df0..a23aa0d4 100644
> --- a/test/tarantool-tests/lj-735-io-close-on-closed-file.test.lua
> +++ b/test/tarantool-tests/lj-735-io-close-on-closed-file.test.lua
> @@ -21,4 +21,4 @@ test:ok(err:match('attempt to use a closed file'), 'correct error message')
>   
>   assert(os.remove(TEST_FILE))
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-762-pcall-no-arg.test.lua b/test/tarantool-tests/lj-762-pcall-no-arg.test.lua
> index 6cbfe707..db16c3dd 100644
> --- a/test/tarantool-tests/lj-762-pcall-no-arg.test.lua
> +++ b/test/tarantool-tests/lj-762-pcall-no-arg.test.lua
> @@ -12,4 +12,4 @@ local result, err = pcall(pcall)
>   test:ok(not result, 'pcall() without args: bad status')
>   test:like(err, 'value expected', 'pcall() without args: error message')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-819-fix-missing-uclo.test.lua b/test/tarantool-tests/lj-819-fix-missing-uclo.test.lua
> index 942c22b2..e2352c92 100644
> --- a/test/tarantool-tests/lj-819-fix-missing-uclo.test.lua
> +++ b/test/tarantool-tests/lj-819-fix-missing-uclo.test.lua
> @@ -112,4 +112,4 @@ local _
>   _, res = pcall(f)
>   test:ok(type(res) == 'function', 'consistency on compilation: type of returned value is correct')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-864-varg-rec-base-offset.test.lua b/test/tarantool-tests/lj-864-varg-rec-base-offset.test.lua
> index d41e33ff..02864e44 100644
> --- a/test/tarantool-tests/lj-864-varg-rec-base-offset.test.lua
> +++ b/test/tarantool-tests/lj-864-varg-rec-base-offset.test.lua
> @@ -24,4 +24,4 @@ end
>   -- due to failing assertion guard for type of loaded vararg slot.
>   test:ok(test_rec_varg(42, 0), 'correct BC_VARG recording')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-906-fix-err-mem.test.lua b/test/tarantool-tests/lj-906-fix-err-mem.test.lua
> index 6c6df338..7235e829 100644
> --- a/test/tarantool-tests/lj-906-fix-err-mem.test.lua
> +++ b/test/tarantool-tests/lj-906-fix-err-mem.test.lua
> @@ -100,4 +100,4 @@ collectgarbage()
>   
>   test:ok(true, 'correctly throw memory error')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-981-folding-0.test.lua b/test/tarantool-tests/lj-981-folding-0.test.lua
> index d156f53d..608cb2cd 100644
> --- a/test/tarantool-tests/lj-981-folding-0.test.lua
> +++ b/test/tarantool-tests/lj-981-folding-0.test.lua
> @@ -60,4 +60,4 @@ test:ok(result == expected, 'TDUP and -0 folding')
>   -- Test that there is no NEWREF -0 IR.
>   test:ok(not traces[1]:has_ir('NEWREF.*-0'), '-0 is canonized for TDUP tab')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-994-instable-types-during-loop-unroll.test.lua b/test/tarantool-tests/lj-994-instable-types-during-loop-unroll.test.lua
> index 78c04f21..730b0e61 100644
> --- a/test/tarantool-tests/lj-994-instable-types-during-loop-unroll.test.lua
> +++ b/test/tarantool-tests/lj-994-instable-types-during-loop-unroll.test.lua
> @@ -50,4 +50,4 @@ end
>   test:is(result, true, 'TDUP load forwarding was successful')
>   ]]
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-flush-on-trace.test.lua b/test/tarantool-tests/lj-flush-on-trace.test.lua
> index fe740087..a64fac4d 100644
> --- a/test/tarantool-tests/lj-flush-on-trace.test.lua
> +++ b/test/tarantool-tests/lj-flush-on-trace.test.lua
> @@ -59,4 +59,4 @@ for _, subtest in pairs(cases) do
>     test[subtest.test](test, output, subtest.expected, subtest.message)
>   end
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/math-modf.test.lua b/test/tarantool-tests/math-modf.test.lua
> index d8421db9..20a3bb16 100644
> --- a/test/tarantool-tests/math-modf.test.lua
> +++ b/test/tarantool-tests/math-modf.test.lua
> @@ -32,3 +32,5 @@ for i = 1, 3 do
>   end
>   
>   test:ok(array_is_consistent(r1) and array_is_consistent(r2), 'wrong modf')
> +
> +test:done(true)
> diff --git a/test/tarantool-tests/misclib-getmetrics-lapi.test.lua b/test/tarantool-tests/misclib-getmetrics-lapi.test.lua
> index 0ee71499..741900b6 100644
> --- a/test/tarantool-tests/misclib-getmetrics-lapi.test.lua
> +++ b/test/tarantool-tests/misclib-getmetrics-lapi.test.lua
> @@ -430,4 +430,4 @@ test:test("tracenum-base", function(subtest)
>       subtest:is(metrics.jit_trace_num, 0)
>   end)
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/misclib-memprof-lapi.test.lua b/test/tarantool-tests/misclib-memprof-lapi.test.lua
> index eae20893..3cb5c8be 100644
> --- a/test/tarantool-tests/misclib-memprof-lapi.test.lua
> +++ b/test/tarantool-tests/misclib-memprof-lapi.test.lua
> @@ -296,4 +296,4 @@ test:test("jit-output", function(subtest)
>     jit.opt.start(unpack(jit_opt_default))
>   end)
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/misclib-sysprof-lapi.test.lua b/test/tarantool-tests/misclib-sysprof-lapi.test.lua
> index 2f0635db..fdaed46a 100644
> --- a/test/tarantool-tests/misclib-sysprof-lapi.test.lua
> +++ b/test/tarantool-tests/misclib-sysprof-lapi.test.lua
> @@ -129,4 +129,4 @@ check_mode("C", 100)
>   
>   os.remove(TMP_BINFILE)
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/or-144-gc64-asmref-l.test.lua b/test/tarantool-tests/or-144-gc64-asmref-l.test.lua
> index 0c352c29..18c6efb2 100644
> --- a/test/tarantool-tests/or-144-gc64-asmref-l.test.lua
> +++ b/test/tarantool-tests/or-144-gc64-asmref-l.test.lua
> @@ -25,4 +25,4 @@ end
>   
>   test:ok(global_env == getfenv(0), 'IR_LREF assembling correctness')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/or-232-unsink-64-kptr.test.lua b/test/tarantool-tests/or-232-unsink-64-kptr.test.lua
> index fc8acaaf..4a0ece89 100644
> --- a/test/tarantool-tests/or-232-unsink-64-kptr.test.lua
> +++ b/test/tarantool-tests/or-232-unsink-64-kptr.test.lua
> @@ -41,4 +41,4 @@ for i = 1, 1000 do
>   end
>   test:ok(true, "allocation is unsunk at the trace exit (no platform failures)")
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/or-94-arm64-ir-ahuvload-bool.test.lua b/test/tarantool-tests/or-94-arm64-ir-ahuvload-bool.test.lua
> index 5418a058..990a3989 100644
> --- a/test/tarantool-tests/or-94-arm64-ir-ahuvload-bool.test.lua
> +++ b/test/tarantool-tests/or-94-arm64-ir-ahuvload-bool.test.lua
> @@ -145,4 +145,4 @@ for i = 1, N_TESTS do
>     jit.flush()
>   end
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/tap.lua b/test/tarantool-tests/tap.lua
> index 47a8fe87..8559ee52 100644
> --- a/test/tarantool-tests/tap.lua
> +++ b/test/tarantool-tests/tap.lua
> @@ -10,7 +10,7 @@ local NULL = ffi.new("void *")
>   local function finalize(test)
>     -- TODO: implement finalization for subtests too.
>     assert(test.parent == nil, 'FIXME: There is no way to use finalize subtest')
> -  os.exit(test:check() and 0 or 1)
> +  test:done(true)
>   end
>   
>   local function indent(level, size)
> @@ -337,12 +337,24 @@ local function skipcond(test, conditions)
>     return test
>   end
>   
> +local function done(test, exit)
> +  if exit then
> +    -- XXX: The second argument is required to properly close Lua
> +    -- universe (i.e. invoke <lua_close> before exiting).
> +    -- XXX: return is added explicitly to force CALLT emitting.
> +    return os.exit(test:check() and 0 or 1, true)
> +  else
> +    assert(test:check(), 'Test check failed')
> +  end
> +end
> +
>   test_mt = {
>     __index = {
>       test       = new,
>       plan       = plan,
>       check      = check,
>       diag       = diag,
> +    done       = done,
>       ok         = ok,
>       fail       = fail,
>       skip       = skip,
> diff --git a/test/tarantool-tests/tonumber-negative-non-decimal-base.test.lua b/test/tarantool-tests/tonumber-negative-non-decimal-base.test.lua
> index 94df3b1f..c7ac6b6f 100644
> --- a/test/tarantool-tests/tonumber-negative-non-decimal-base.test.lua
> +++ b/test/tarantool-tests/tonumber-negative-non-decimal-base.test.lua
> @@ -26,4 +26,4 @@ test:ok(tonumber('- 1010  ', 2) == nil, 'space between sign and value')
>   test:ok(tonumber('-_1010  ', 2) == nil,
>   	'invalid character between sign and value')
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/tools-utils-avl.test.lua b/test/tarantool-tests/tools-utils-avl.test.lua
> index ebcfac2e..d7aa5011 100644
> --- a/test/tarantool-tests/tools-utils-avl.test.lua
> +++ b/test/tarantool-tests/tools-utils-avl.test.lua
> @@ -38,4 +38,4 @@ test:is(avl.floor(root, -10), nil)
>   -- Not exact upper bound.
>   test:is(avl.floor(root, 2.75), 2)
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)
> diff --git a/test/tarantool-tests/unit-jit-parse.test.lua b/test/tarantool-tests/unit-jit-parse.test.lua
> index 24216e87..2e6a2228 100644
> --- a/test/tarantool-tests/unit-jit-parse.test.lua
> +++ b/test/tarantool-tests/unit-jit-parse.test.lua
> @@ -42,4 +42,4 @@ for irnum = 1, N_TESTS do
>     test:ok(irref, 'find IR refernce by pattern: ' .. ir_pattern)
>   end
>   
> -os.exit(test:check() and 0 or 1)
> +test:done(true)

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 4/5] build: introduce LUAJIT_USE_ASAN option
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 4/5] build: introduce LUAJIT_USE_ASAN option Igor Munkin via Tarantool-patches
@ 2023-07-24 11:41   ` Sergey Bronnikov via Tarantool-patches
  2023-07-26 13:06     ` Igor Munkin via Tarantool-patches
  2023-07-25 12:26   ` Sergey Bronnikov via Tarantool-patches
  2023-07-26 11:03   ` Sergey Kaplun via Tarantool-patches
  2 siblings, 1 reply; 25+ messages in thread
From: Sergey Bronnikov via Tarantool-patches @ 2023-07-24 11:41 UTC (permalink / raw)
  To: Igor Munkin, Sergey Kaplun; +Cc: tarantool-patches

Thanks for the patch! See comments below.


On 7/21/23 11:12, Igor Munkin wrote:
> There was neither a special option nor a variable to configure the
> sanitizers support via the build system since the commit
> 052c1a32a5e74b337686eee229d089d576775931 ("Add preliminary ASAN
> support") where ASan support had been introduced. We finally decided to
> use this feature in LuaJIT CI, so for convenient build configuration
> LUAJIT_USE_ASAN option is added to the root CMakeLists.txt.
>
> Resolves tarantool/tarantool#5878
>
> Co-authored-by: Sergey Kaplun <skaplun@tarantool.org>
> Signed-off-by: Igor Munkin <imun@tarantool.org>
> ---
>   CMakeLists.txt | 33 ++++++++++++++++++++++++---------
>   1 file changed, 24 insertions(+), 9 deletions(-)
>
> diff --git a/CMakeLists.txt b/CMakeLists.txt
> index 6ef24bba..c4664cf9 100644
> --- a/CMakeLists.txt
> +++ b/CMakeLists.txt

<snipped>


> +# ASan enabled.
> +option(LUAJIT_USE_ASAN "Build LuaJIT with AddressSanitizer" OFF)
> +if(LUAJIT_USE_ASAN)
> +  if(NOT LUAJIT_USE_SYSMALLOC)
> +    message(WARNING
> +      "Unfortunately, internal LuaJIT memory allocator is not instrumented yet,"
> +      " so to find any memory errors it's better to build LuaJIT with system"
> +      " provided memory allocator (i.e. run CMake configuration phase with"
> +      " -DLUAJIT_USE_SYSMALLOC=ON)."
> +    )
> +  endif()
> +  # Use all recomendations described in AddressSanitize docs:

typo: recomendations -> recommendations


<snipped>


With applied patch tests below failed:


LUA_PATH="test/tarantool-tests/?.lua;src/?.lua;;./src/jit/?.lua;./tools/?.lua;" 
./src/luajit test/tarantool-tests/lj-128-fix-union-init.test.lua


=================================================================
==558476==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 2048 byte(s) in 1 object(s) allocated from:
     #0 0x55f75b19c1f5 in realloc 
(/home/sergeyb/sources/MRG/tarantool/third_party/luajit/src/luajit+0xd81f5) 
(BuildId: 3f595aa9bf0b93395cadf9c7246b933ded2a6a0e)
     #1 0x55f75b230295 in mem_alloc lib_aux.c
     #2 0x55f75b205066 in lj_mem_realloc 
(/home/sergeyb/sources/MRG/tarantool/third_party/luajit/src/luajit+0x141066) 
(BuildId: 3f595aa9bf0b93395cadf9c7246b933ded2a6a0e)
     #3 0x55f75b2aa6fb in lj_ir_growbot lj_ir.c
     #4 0x55f75b2a78de in lj_ir_kgc 
(/home/sergeyb/sources/MRG/tarantool/third_party/luajit/src/luajit+0x1e38de) 
(BuildId: 3f595aa9bf0b93395cadf9c7246b933ded2a6a0e)
     #5 0x55f75b37f7c7 in lj_record_constify 
(/home/sergeyb/sources/MRG/tarantool/third_party/luajit/src/luajit+0x2bb7c7) 
(BuildId: 3f595aa9bf0b93395cadf9c7246b933ded2a6a0e)
     #6 0x55f75b398876 in rec_upvalue lj_record.c
     #7 0x55f75b3923db in lj_record_ins 
(/home/sergeyb/sources/MRG/tarantool/third_party/luajit/src/luajit+0x2ce3db) 
(BuildId: 3f595aa9bf0b93395cadf9c7246b933ded2a6a0e)
     #8 0x55f75b2ae826 in trace_state lj_trace.c
     #9 0x55f75b335eb4 in lj_vm_cpcall 
(/home/sergeyb/sources/MRG/tarantool/third_party/luajit/src/luajit+0x271eb4) 
(BuildId: 3f595aa9bf0b93395cadf9c7246b933ded2a6a0e)

SUMMARY: AddressSanitizer: 2048 byte(s) leaked in 1 allocation(s).


$ 
LUA_PATH="test/tarantool-tests/?.lua;src/?.lua;;./src/jit/?.lua;./tools/?.lua;" 
./src/luajit test/tarantool-tests/lj-1024-varg-maxslot.test.lua
TAP version 13
1..2
ok - BC_VARG recording 0th frame depth
ok - BC_VARG recording with VARG slots defined on trace

=================================================================
==558552==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 2048 byte(s) in 1 object(s) allocated from:
     #0 0x55db03d981f5 in realloc 
(/home/sergeyb/sources/MRG/tarantool/third_party/luajit/src/luajit+0xd81f5) 
(BuildId: 3f595aa9bf0b93395cadf9c7246b933ded2a6a0e)
     #1 0x55db03e2c295 in mem_alloc lib_aux.c
     #2 0x55db03e01066 in lj_mem_realloc 
(/home/sergeyb/sources/MRG/tarantool/third_party/luajit/src/luajit+0x141066) 
(BuildId: 3f595aa9bf0b93395cadf9c7246b933ded2a6a0e)
     #3 0x55db03ea66fb in lj_ir_growbot lj_ir.c
     #4 0x55db03ea38de in lj_ir_kgc 
(/home/sergeyb/sources/MRG/tarantool/third_party/luajit/src/luajit+0x1e38de) 
(BuildId: 3f595aa9bf0b93395cadf9c7246b933ded2a6a0e)
     #5 0x55db03f8c4f2 in lj_record_ins 
(/home/sergeyb/sources/MRG/tarantool/third_party/luajit/src/luajit+0x2cc4f2) 
(BuildId: 3f595aa9bf0b93395cadf9c7246b933ded2a6a0e)
     #6 0x55db03eaa826 in trace_state lj_trace.c
     #7 0x55db03f31eb4 in lj_vm_cpcall 
(/home/sergeyb/sources/MRG/tarantool/third_party/luajit/src/luajit+0x271eb4) 
(BuildId: 3f595aa9bf0b93395cadf9c7246b933ded2a6a0e)

SUMMARY: AddressSanitizer: 2048 byte(s) leaked in 1 allocation(s).


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 5/5] ci: introduce testing workflow with sanitizers
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 5/5] ci: introduce testing workflow with sanitizers Igor Munkin via Tarantool-patches
@ 2023-07-24 11:54   ` Sergey Bronnikov via Tarantool-patches
  2023-07-26 14:53     ` Igor Munkin via Tarantool-patches
  2023-07-26 11:29   ` Sergey Kaplun via Tarantool-patches
  1 sibling, 1 reply; 25+ messages in thread
From: Sergey Bronnikov via Tarantool-patches @ 2023-07-24 11:54 UTC (permalink / raw)
  To: Igor Munkin, Sergey Kaplun; +Cc: tarantool-patches

Thanks for the patch!

See my comments below.


Sergey

On 7/21/23 11:12, Igor Munkin wrote:


<snipped>

> diff --git a/.github/actions/setup-sanitizers/README.md b/.github/actions/setup-sanitizers/README.md
> new file mode 100644
> index 00000000..3aa9e214
> --- /dev/null
> +++ b/.github/actions/setup-sanitizers/README.md
> @@ -0,0 +1,12 @@
> +# Setup environment for sanitizers on Linux
> +
> +Action setups the environment on Linux runners (install requirements, setup the
> +workflow environment, etc) for testing with sanitizers enabled.
> +
> +## How to use Github Action from Github workflow
> +
> +Add the following code to the running steps before LuaJIT configuration:
> +```
> +- uses: ./.github/actions/setup-sanitizers
> +  if: ${{ matrix.OS == 'Linux' }}

Nit: I would left a comment why OSes is limited by Linux only.

You actually said it in commit message ("I believe we will
be able to add other platforms being supported, when macOS runners
starvation is defeated.").

> +```
> diff --git a/.github/actions/setup-sanitizers/action.yml b/.github/actions/setup-sanitizers/action.yml
> new file mode 100644
> index 00000000..ca6b6b9f
> --- /dev/null
> +++ b/.github/actions/setup-sanitizers/action.yml
> @@ -0,0 +1,24 @@
> +name: Setup CI environment for testing with sanitizers on Linux
> +description: Common part to tweak Linux CI runner environment for sanitizers
> +runs:
> +  using: composite
> +  steps:
> +    - name: Setup CI environment
> +      uses: ./.github/actions/setup
> +    - name: Set CMAKE_BUILD_PARALLEL_LEVEL
> +      run: |
> +        # Set CMAKE_BUILD_PARALLEL_LEVEL environment variable to
> +        # limit the number of parallel jobs for build/test step.
> +        NPROC=$(nproc)
> +        echo CMAKE_BUILD_PARALLEL_LEVEL=$(($NPROC + 1)) | tee -a $GITHUB_ENV
> +      shell: bash
> +    - name: Install build and test dependencies
> +      run: |
> +        apt -y update
> +        apt -y install clang-11 cmake ninja-build make perl
> +      shell: bash
> +    - name: Set Clang as a default toolchain
> +      run: |
> +        echo CC=clang-11 | tee -a $GITHUB_ENV
> +        echo CXX=clang++-11 | tee -a $GITHUB_ENV
> +      shell: bash
> diff --git a/.github/workflows/sanitizers-testing.yml b/.github/workflows/sanitizers-testing.yml
> new file mode 100644
> index 00000000..6c345108
> --- /dev/null
> +++ b/.github/workflows/sanitizers-testing.yml
> @@ -0,0 +1,89 @@
> +name: Sanitizers testing
> +
> +on:
> +  push:
> +    branches-ignore:
> +      - '**-notest'
> +      - 'upstream-**'
> +    tags-ignore:
> +      - '**'
> +
> +concurrency:
> +  # An update of a developer branch cancels the previously
> +  # scheduled workflow run for this branch. However, the default
> +  # branch, and long-term branch (tarantool/release/2.11,
> +  # tarantool/release/2.10, etc) workflow runs are never canceled.
> +  #
> +  # We use a trick here: define the concurrency group as 'workflow
> +  # run ID' + # 'workflow run attempt' because it is a unique
> +  # combination for any run. So it effectively discards grouping.
> +  #
> +  # XXX: we cannot use `github.sha` as a unique identifier because
> +  # pushing a tag may cancel a run that works on a branch push
> +  # event.
> +  group: ${{ startsWith(github.ref, 'refs/heads/tarantool/')
> +    && format('{0}-{1}', github.run_id, github.run_attempt)
> +    || format('{0}-{1}', github.workflow, github.ref) }}
> +  cancel-in-progress: true
> +
> +jobs:
> +  test-asan:
> +    strategy:
> +      fail-fast: false
> +      matrix:
> +        # XXX: Let's start with only Linux/x86_64
> +        BUILDTYPE: [Debug, Release]
> +        include:
> +          - BUILDTYPE: Debug
> +            CMAKEFLAGS: -DCMAKE_BUILD_TYPE=Debug -DLUA_USE_ASSERT=ON -DLUA_USE_APICHECK=ON
> +          - BUILDTYPE: Release
> +            CMAKEFLAGS: -DCMAKE_BUILD_TYPE=RelWithDebInfo
> +    runs-on: [self-hosted, regular, Linux, x86_64]
> +    name: >
> +      LuaJIT with ASan (Linux/x86_64)
> +      ${{ matrix.BUILDTYPE }}
> +      GC64:ON SYSMALLOC:ON
> +    steps:
> +      - uses: actions/checkout@v3
> +        with:
> +          fetch-depth: 0
> +          submodules: recursive
> +      - name: setup Linux for sanitizers
> +        uses: ./.github/actions/setup-sanitizers
> +      - name: configure
> +        run: >
> +          cmake -S . -B ${{ env.BUILDDIR }}
> +          -G Ninja
> +          ${{ matrix.CMAKEFLAGS }}
> +          -DLUAJIT_USE_ASAN=ON
> +          # XXX: Unfortunately, internal LuaJIT memory allocator
> +          # is not instrumented yet, so to find any memory errors
> +          # it's better to build LuaJIT with system provided
> +          # memory allocator (i.e. run CMake configuration phase
> +          # with -DLUAJIT_USE_SYSMALLOC=ON). For more info, see
> +          # root CMakeLists.txt.
> +          -DLUAJIT_USE_SYSMALLOC=ON
> +          # XXX: LUAJIT_USE_SYSMALLOC cannot be enabled on x64
> +          # without GC64, since realloc usually doesn't return
> +          # addresses in the right address range. For more info,
> +          # see root CMakeLists.txt.
> +          -DLUAJIT_ENABLE_GC64=ON
Nit: I suppose it would be easy read paragraph above if indent it by 
"-S", not by "cmake".
> +      - name: build
> +        run: cmake --build . --parallel
> +        working-directory: ${{ env.BUILDDIR }}
> +      - name: test
> +        env:
> +          # Enable as much checks as possible. See more info here:
> +          # https://github.com/google/sanitizers/wiki/AddressSanitizerFlags.
> +          ASAN_OPTIONS: "                    \
> +            detect_invalid_pointer_pairs=1:  \
> +            detect_leaks=1:                  \
> +            detect_stack_use_after_return=1: \
> +            dump_instruction_bytes=1:        \
> +            heap_profile=0:                  \
> +            print_suppressions=0             \
> +            symbolize=1:                     \
> +            unmap_shadow_on_exit=1:          \
> +          "

This options are used in CI and doesn't present in CMake, so ASAN will 
work different locally and in CI.

Is it expected?

> +        run: cmake --build . --parallel --target LuaJIT-test
> +        working-directory: ${{ env.BUILDDIR }}

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 4/5] build: introduce LUAJIT_USE_ASAN option
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 4/5] build: introduce LUAJIT_USE_ASAN option Igor Munkin via Tarantool-patches
  2023-07-24 11:41   ` Sergey Bronnikov via Tarantool-patches
@ 2023-07-25 12:26   ` Sergey Bronnikov via Tarantool-patches
  2023-07-26 12:54     ` Igor Munkin via Tarantool-patches
  2023-07-26 11:03   ` Sergey Kaplun via Tarantool-patches
  2 siblings, 1 reply; 25+ messages in thread
From: Sergey Bronnikov via Tarantool-patches @ 2023-07-25 12:26 UTC (permalink / raw)
  To: Igor Munkin, Sergey Kaplun; +Cc: tarantool-patches

Hello, again


On 7/21/23 11:12, Igor Munkin wrote:


<snipped>

> +option(LUAJIT_USE_ASAN "Build LuaJIT with AddressSanitizer" OFF)
> +if(LUAJIT_USE_ASAN)
> +  if(NOT LUAJIT_USE_SYSMALLOC)
> +    message(WARNING
> +      "Unfortunately, internal LuaJIT memory allocator is not instrumented yet,"
> +      " so to find any memory errors it's better to build LuaJIT with system"
> +      " provided memory allocator (i.e. run CMake configuration phase with"
> +      " -DLUAJIT_USE_SYSMALLOC=ON)."
> +    )
> +  endif()
> +  # Use all recomendations described in AddressSanitize docs:
> +  # https://clang.llvm.org/docs/AddressSanitizer.html.
> +  AppendFlags(CMAKE_C_FLAGS
> +    # Enable hints for AddressSanitizer (see src/lj_str.c).
> +    -DLUAJIT_USE_ASAN
> +    # XXX: To get nicer stack traces in error messages.
> +    -fno-omit-frame-pointer
> +    # Enable AddressSanitizer support.
> +    -fsanitize=address
> +  )
> +endif()
>   

I suspect we need set in LUAJIT_USE_SYSMALLOC in cmake/luajit.cmake [1] 
on next LuaJIT bump, right?

Otherwise Tarantool CI will fail.


1. 
https://github.com/tarantool/tarantool/blob/1cda22aaaf7eb1f0880f4c70f2c79ce27a9604ce/cmake/luajit.cmake#L74-L76


>   # --- Main source tree ---------------------------------------------------------
>   

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 1/5] ci: clean up workflow for exotic builds
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 1/5] ci: clean up workflow for exotic builds Igor Munkin via Tarantool-patches
  2023-07-24 10:36   ` Sergey Bronnikov via Tarantool-patches
@ 2023-07-26  9:37   ` Sergey Kaplun via Tarantool-patches
  1 sibling, 0 replies; 25+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2023-07-26  9:37 UTC (permalink / raw)
  To: Igor Munkin; +Cc: tarantool-patches

Hi, Igor!
Thanks for the patch!
LGTM!

-- 
Best regards,
Sergey Kaplun

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 2/5] memprof: remove invalid assertions
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 2/5] memprof: remove invalid assertions Igor Munkin via Tarantool-patches
  2023-07-24 10:46   ` Sergey Bronnikov via Tarantool-patches
@ 2023-07-26  9:41   ` Sergey Kaplun via Tarantool-patches
  1 sibling, 0 replies; 25+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2023-07-26  9:41 UTC (permalink / raw)
  To: Igor Munkin; +Cc: tarantool-patches

Hi, Igor!
Thanks for the patch!
LGTM!

-- 
Best regards,
Sergey Kaplun

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 3/5] test: introduce test:done TAP helper
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 3/5] test: introduce test:done TAP helper Igor Munkin via Tarantool-patches
  2023-07-24 10:53   ` Sergey Bronnikov via Tarantool-patches
@ 2023-07-26 10:43   ` Sergey Kaplun via Tarantool-patches
  2023-07-26 12:42     ` Igor Munkin via Tarantool-patches
  1 sibling, 1 reply; 25+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2023-07-26 10:43 UTC (permalink / raw)
  To: Igor Munkin; +Cc: tarantool-patches

Hi, Igor!
Thanks for the patch!
LGTM, except a minor nits regarding the commit message.

On 21.07.23, Igor Munkin wrote:
> Before the patch all tests (except <lj-603-err-snap-restore.test.lua>)

Typo: s/Before the patch/Before the patch,/

> in tarantool-tests suite terminate their execution via <os.exit> with
> the status depending on the test results. However, the second argument
> of <os.exit> was omitted and Lua universe was not properly finalized as

Typo: s/omitted and/omitted, and/

> a result. This behaviour becomes a problem, when LuaJIT is build with

Typo: s/build/built/

> LUAJIT_USE_SYSMALLOC option and AddressSanitizer support enabled, since
> the sanitizer starts reporting false positive errors about the memory
> allocations without the corresponding memory releases. To resolve these
> errors, the second parameter to each <os.exit> call terminating the test
> has to be added.
> 
> To avoid loss of the aforementioned parameter in future, <test:done>

Typo: s/in future/in the future/

> helper has been added to the TAP module. Depending on the single
> parameter, the new helper either properly finalize the test being run,
> or simply checks all the test assertions and raises an error if any of
> them fail. The latter case is added especially to handle the specifics
> of <lj-603-err-snap-restore.test.lua> and still check that everything
> works fine.
> 
> Needed for tarantool/tarantool#5878
> 
> Signed-off-by: Igor Munkin <imun@tarantool.org>
> ---

<snipped>

> +local function done(test, exit)
> +  if exit then
> +    -- XXX: The second argument is required to properly close Lua
> +    -- universe (i.e. invoke <lua_close> before exiting).
> +    -- XXX: return is added explicitly to force CALLT emitting.

Side note: Is there a place, where it is important?

> +    return os.exit(test:check() and 0 or 1, true)
> +  else
> +    assert(test:check(), 'Test check failed')
> +  end
> +end

<snipped>

> -- 
> 2.30.2
> 

-- 
Best regards,
Sergey Kaplun

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 4/5] build: introduce LUAJIT_USE_ASAN option
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 4/5] build: introduce LUAJIT_USE_ASAN option Igor Munkin via Tarantool-patches
  2023-07-24 11:41   ` Sergey Bronnikov via Tarantool-patches
  2023-07-25 12:26   ` Sergey Bronnikov via Tarantool-patches
@ 2023-07-26 11:03   ` Sergey Kaplun via Tarantool-patches
  2 siblings, 0 replies; 25+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2023-07-26 11:03 UTC (permalink / raw)
  To: Igor Munkin; +Cc: tarantool-patches

Hi, Igor!
Thanks for the patch!
LGTM, after fixing Sergey's comments.

<snipped>

-- 
Best regards,
Sergey Kaplun

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 5/5] ci: introduce testing workflow with sanitizers
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 5/5] ci: introduce testing workflow with sanitizers Igor Munkin via Tarantool-patches
  2023-07-24 11:54   ` Sergey Bronnikov via Tarantool-patches
@ 2023-07-26 11:29   ` Sergey Kaplun via Tarantool-patches
  2023-07-26 16:35     ` Igor Munkin via Tarantool-patches
  1 sibling, 1 reply; 25+ messages in thread
From: Sergey Kaplun via Tarantool-patches @ 2023-07-26 11:29 UTC (permalink / raw)
  To: Igor Munkin; +Cc: tarantool-patches

Hi, Igor!
Thanks for the patch!
The patch is generally LGTM, after fixing Sergey's comments. But I'm
really concerned about the fact, that the CI don't show any error for
lj-1024-* [1], lj-128-* [2] tests, where we have obvious memleak, since
`os.exit()` is used instead of `test:done(true)` for these tests.

On 21.07.23, Igor Munkin wrote:
> This commit adds GitHub workflow running all available LuaJIT tests with
> LUAJIT_USE_ASAN option enabled. For now, sanitizers workflow works only
> for Linux/x86_64 as the most scaling setup in our CI. I believe we will
> be able to add other platforms being supported, when macOS runners
> starvation is defeated. There is also a separate GitHub Action
> introduced for convenient setup of the environment.
> 
> Besided, internal LuaJIT memory allocator is not instrumented yet

Typo? s/Besided/Besides/
Typo: s/internal ... allocator/the internal ... allocator/

> unfortunately, so to find any memory faults it's better to build LuaJIT
> with system provided memory allocator (i.e. run CMake configuration
> phase with -DLUAJIT_USE_SYSMALLOC=ON). However, LUAJIT_USE_SYSMALLOC
> cannot be enabled on x64 without GC64, since realloc usually doesn't
> return addresses in the right address range. For more info, see root
> CMakeLists.txt.
> 
> Follows up tarantool/tarantool#5878
> 
> Signed-off-by: Igor Munkin <imun@tarantool.org>
> ---
>  .github/actions/setup-sanitizers/README.md  | 12 +++
>  .github/actions/setup-sanitizers/action.yml | 24 ++++++
>  .github/workflows/sanitizers-testing.yml    | 89 +++++++++++++++++++++

<snipped>

> diff --git a/.github/actions/setup-sanitizers/action.yml b/.github/actions/setup-sanitizers/action.yml
> new file mode 100644
> index 00000000..ca6b6b9f
> --- /dev/null
> +++ b/.github/actions/setup-sanitizers/action.yml
> @@ -0,0 +1,24 @@
> +name: Setup CI environment for testing with sanitizers on Linux
> +description: Common part to tweak Linux CI runner environment for sanitizers
> +runs:
> +  using: composite
> +  steps:
> +    - name: Setup CI environment
> +      uses: ./.github/actions/setup
> +    - name: Set CMAKE_BUILD_PARALLEL_LEVEL
> +      run: |
> +        # Set CMAKE_BUILD_PARALLEL_LEVEL environment variable to
> +        # limit the number of parallel jobs for build/test step.
> +        NPROC=$(nproc)
> +        echo CMAKE_BUILD_PARALLEL_LEVEL=$(($NPROC + 1)) | tee -a $GITHUB_ENV
> +      shell: bash
> +    - name: Install build and test dependencies
> +      run: |
> +        apt -y update
> +        apt -y install clang-11 cmake ninja-build make perl
> +      shell: bash
> +    - name: Set Clang as a default toolchain
> +      run: |
> +        echo CC=clang-11 | tee -a $GITHUB_ENV
> +        echo CXX=clang++-11 | tee -a $GITHUB_ENV

Do we need clang++ for LuaJIT? Why?

> +      shell: bash
> diff --git a/.github/workflows/sanitizers-testing.yml b/.github/workflows/sanitizers-testing.yml
> new file mode 100644
> index 00000000..6c345108
> --- /dev/null
> +++ b/.github/workflows/sanitizers-testing.yml

<snipped>

> +      - name: configure
> +        run: >
> +          cmake -S . -B ${{ env.BUILDDIR }}
> +          -G Ninja
> +          ${{ matrix.CMAKEFLAGS }}
> +          -DLUAJIT_USE_ASAN=ON
> +          # XXX: Unfortunately, internal LuaJIT memory allocator
> +          # is not instrumented yet, so to find any memory errors
> +          # it's better to build LuaJIT with system provided
> +          # memory allocator (i.e. run CMake configuration phase
> +          # with -DLUAJIT_USE_SYSMALLOC=ON). For more info, see
> +          # root CMakeLists.txt.
> +          -DLUAJIT_USE_SYSMALLOC=ON
> +          # XXX: LUAJIT_USE_SYSMALLOC cannot be enabled on x64
> +          # without GC64, since realloc usually doesn't return
> +          # addresses in the right address range. For more info,
> +          # see root CMakeLists.txt.
> +          -DLUAJIT_ENABLE_GC64=ON
> +      - name: build
> +        run: cmake --build . --parallel
> +        working-directory: ${{ env.BUILDDIR }}
> +      - name: test
> +        env:
> +          # Enable as much checks as possible. See more info here:
> +          # https://github.com/google/sanitizers/wiki/AddressSanitizerFlags.

Please, also add the link to the [1], since heap_profile is common flag
(same for print_suppressions). Also, it is disabled by default, why do
we need to forcify it to false?

> +          ASAN_OPTIONS: "                    \
> +            detect_invalid_pointer_pairs=1:  \
> +            detect_leaks=1:                  \
> +            detect_stack_use_after_return=1: \
> +            dump_instruction_bytes=1:        \
> +            heap_profile=0:                  \
> +            print_suppressions=0             \
> +            symbolize=1:                     \
> +            unmap_shadow_on_exit=1:          \
> +          "
> +        run: cmake --build . --parallel --target LuaJIT-test
> +        working-directory: ${{ env.BUILDDIR }}
> -- 
> 2.30.2
> 

[1]: https://github.com/tarantool/luajit/actions/runs/5619185186/job/15225900726#step:6:673
[2]: https://github.com/tarantool/luajit/actions/runs/5619185186/job/15225900726#step:6:638
[3]: https://github.com/google/sanitizers/wiki/SanitizerCommonFlags

-- 
Best regards,
Sergey Kaplun

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 3/5] test: introduce test:done TAP helper
  2023-07-26 10:43   ` Sergey Kaplun via Tarantool-patches
@ 2023-07-26 12:42     ` Igor Munkin via Tarantool-patches
  0 siblings, 0 replies; 25+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2023-07-26 12:42 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Sergey,

Thanks for your review! Fixed all the typos you've found.

On 26.07.23, Sergey Kaplun wrote:
> Hi, Igor!
> Thanks for the patch!
> LGTM, except a minor nits regarding the commit message.
> 
> On 21.07.23, Igor Munkin wrote:

<snipped>

> > +local function done(test, exit)
> > +  if exit then
> > +    -- XXX: The second argument is required to properly close Lua
> > +    -- universe (i.e. invoke <lua_close> before exiting).
> > +    -- XXX: return is added explicitly to force CALLT emitting.
> 
> Side note: Is there a place, where it is important?

No, there's not. Prosto po prikolu.

> 
> > +    return os.exit(test:check() and 0 or 1, true)
> > +  else
> > +    assert(test:check(), 'Test check failed')
> > +  end
> > +end
> 
> <snipped>
> 
> > -- 
> > 2.30.2
> > 
> 
> -- 
> Best regards,
> Sergey Kaplun

-- 
Best regards,
IM

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 4/5] build: introduce LUAJIT_USE_ASAN option
  2023-07-25 12:26   ` Sergey Bronnikov via Tarantool-patches
@ 2023-07-26 12:54     ` Igor Munkin via Tarantool-patches
  2023-07-27 11:06       ` Sergey Bronnikov via Tarantool-patches
  0 siblings, 1 reply; 25+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2023-07-26 12:54 UTC (permalink / raw)
  To: Sergey Bronnikov; +Cc: tarantool-patches

Sergey,

Thanks for your review! Please consider my answer inline (though, we've
already discussed it offline).

On 25.07.23, Sergey Bronnikov wrote:
> Hello, again
> 
> 
> On 7/21/23 11:12, Igor Munkin wrote:

<snipped>

> 
> I suspect we need set in LUAJIT_USE_SYSMALLOC in cmake/luajit.cmake [1] on
> next LuaJIT bump, right?

Again, all problems come from #3071[1]: lua_State is not closed in scope
of the patched <os.exit> in Tarantool. Hence, leaks occur in ASan/LSan
reports (even with true given as a second parameter of <os.exit>). Until
this issue is not resolved, LUAJIT_USE_SYSMALLOC will report lots of
"false positives" issues (at least, I can't prove that these are real
leaks in LuaJIT/Tarantool). I'll change this when #3071 is resolved (the
same way it's done for LUAJIT_USE_VALGRIND).

Hence, LuaJIT-related ASan checks is relaxed in Tarantool, but we have
strong validation in LuaJIT CI.

> 
> Otherwise Tarantool CI will fail.
> 
> 
> 1. https://github.com/tarantool/tarantool/blob/1cda22aaaf7eb1f0880f4c70f2c79ce27a9604ce/cmake/luajit.cmake#L74-L76
> 
> 
> >   # --- Main source tree ---------------------------------------------------------

[1]: https://github.com/tarantool/tarantool/issues/3071

-- 
Best regards,
IM

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 4/5] build: introduce LUAJIT_USE_ASAN option
  2023-07-24 11:41   ` Sergey Bronnikov via Tarantool-patches
@ 2023-07-26 13:06     ` Igor Munkin via Tarantool-patches
  0 siblings, 0 replies; 25+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2023-07-26 13:06 UTC (permalink / raw)
  To: Sergey Bronnikov; +Cc: tarantool-patches

Sergey,

Thanks for your review! See my answers below.

On 24.07.23, Sergey Bronnikov wrote:
> Thanks for the patch! See comments below.
> 
> 
> On 7/21/23 11:12, Igor Munkin wrote:

<snipped>

> > +# ASan enabled.
> > +option(LUAJIT_USE_ASAN "Build LuaJIT with AddressSanitizer" OFF)
> > +if(LUAJIT_USE_ASAN)
> > +  if(NOT LUAJIT_USE_SYSMALLOC)
> > +    message(WARNING
> > +      "Unfortunately, internal LuaJIT memory allocator is not instrumented yet,"
> > +      " so to find any memory errors it's better to build LuaJIT with system"
> > +      " provided memory allocator (i.e. run CMake configuration phase with"
> > +      " -DLUAJIT_USE_SYSMALLOC=ON)."
> > +    )
> > +  endif()
> > +  # Use all recomendations described in AddressSanitize docs:
> 
> typo: recomendations -> recommendations

Fixed, thanks!

> 

<snipped>

> 
> With applied patch tests below failed:

My bad: I've made inaccurate rebase on the bleeding master and forgotten
to update tests added by Max and Sergey. See the iterative diff:

================================================================================

diff --git a/test/tarantool-tests/lj-1024-varg-maxslot.test.lua b/test/tarantool-tests/lj-1024-varg-maxslot.test.lua
index e33ddba2..81fb1eea 100644
--- a/test/tarantool-tests/lj-1024-varg-maxslot.test.lua
+++ b/test/tarantool-tests/lj-1024-varg-maxslot.test.lua
@@ -60,4 +60,4 @@ end
 
 test:ok(true, 'BC_VARG recording with VARG slots defined on trace')
 
-os.exit(test:check() and 0 or 1)
+test:done(true)
diff --git a/test/tarantool-tests/lj-128-fix-union-init.test.lua b/test/tarantool-tests/lj-128-fix-union-init.test.lua
index 93cbf3af..b36758fc 100644
--- a/test/tarantool-tests/lj-128-fix-union-init.test.lua
+++ b/test/tarantool-tests/lj-128-fix-union-init.test.lua
@@ -55,4 +55,4 @@ for i = 1, NITERATIONS do
   test:ok(union_type(i).u == i, 'first member init only')
 end
 
-os.exit(test:check() and 0 or 1)
+test:done(true)

================================================================================

Thanks for manual testing this, since it was covered by another bug in
CI (see the explanation in the next patch).

> 

<snipped>

> 

-- 
Best regards,
IM

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 5/5] ci: introduce testing workflow with sanitizers
  2023-07-24 11:54   ` Sergey Bronnikov via Tarantool-patches
@ 2023-07-26 14:53     ` Igor Munkin via Tarantool-patches
  2023-07-27 11:13       ` Sergey Bronnikov via Tarantool-patches
  0 siblings, 1 reply; 25+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2023-07-26 14:53 UTC (permalink / raw)
  To: Sergey Bronnikov; +Cc: tarantool-patches

Sergey,

Thanks for your review! See my answers inline.

On 24.07.23, Sergey Bronnikov wrote:
> Thanks for the patch!
> 
> See my comments below.
> 
> 
> Sergey
> 
> On 7/21/23 11:12, Igor Munkin wrote:
> 

<snipped>

> > diff --git a/.github/actions/setup-sanitizers/README.md b/.github/actions/setup-sanitizers/README.md
> > new file mode 100644
> > index 00000000..3aa9e214
> > --- /dev/null
> > +++ b/.github/actions/setup-sanitizers/README.md
> > @@ -0,0 +1,12 @@
> > +# Setup environment for sanitizers on Linux
> > +
> > +Action setups the environment on Linux runners (install requirements, setup the
> > +workflow environment, etc) for testing with sanitizers enabled.
> > +
> > +## How to use Github Action from Github workflow
> > +
> > +Add the following code to the running steps before LuaJIT configuration:
> > +```
> > +- uses: ./.github/actions/setup-sanitizers
> > +  if: ${{ matrix.OS == 'Linux' }}
> 
> Nit: I would left a comment why OSes is limited by Linux only.
> 
> You actually said it in commit message ("I believe we will
> be able to add other platforms being supported, when macOS runners
> starvation is defeated.").

I have literally written it here (see the first paragraph at the
beginning of the README.md).
| Action setups the environment on Linux runners (install requirements,
| setup the workflow environment, etc) for testing with sanitizers
| enabled.

> 
> > +```

<snipped>

> > diff --git a/.github/workflows/sanitizers-testing.yml b/.github/workflows/sanitizers-testing.yml
> > new file mode 100644
> > index 00000000..6c345108
> > --- /dev/null
> > +++ b/.github/workflows/sanitizers-testing.yml
> > @@ -0,0 +1,89 @@

<snipped>

> > +jobs:
> > +  test-asan:
> > +    strategy:
> > +      fail-fast: false
> > +      matrix:
> > +        # XXX: Let's start with only Linux/x86_64
> > +        BUILDTYPE: [Debug, Release]
> > +        include:
> > +          - BUILDTYPE: Debug
> > +            CMAKEFLAGS: -DCMAKE_BUILD_TYPE=Debug -DLUA_USE_ASSERT=ON -DLUA_USE_APICHECK=ON
> > +          - BUILDTYPE: Release
> > +            CMAKEFLAGS: -DCMAKE_BUILD_TYPE=RelWithDebInfo
> > +    runs-on: [self-hosted, regular, Linux, x86_64]
> > +    name: >
> > +      LuaJIT with ASan (Linux/x86_64)
> > +      ${{ matrix.BUILDTYPE }}
> > +      GC64:ON SYSMALLOC:ON
> > +    steps:
> > +      - uses: actions/checkout@v3
> > +        with:
> > +          fetch-depth: 0
> > +          submodules: recursive
> > +      - name: setup Linux for sanitizers
> > +        uses: ./.github/actions/setup-sanitizers
> > +      - name: configure
> > +        run: >
> > +          cmake -S . -B ${{ env.BUILDDIR }}
> > +          -G Ninja
> > +          ${{ matrix.CMAKEFLAGS }}
> > +          -DLUAJIT_USE_ASAN=ON
> > +          # XXX: Unfortunately, internal LuaJIT memory allocator
> > +          # is not instrumented yet, so to find any memory errors
> > +          # it's better to build LuaJIT with system provided
> > +          # memory allocator (i.e. run CMake configuration phase
> > +          # with -DLUAJIT_USE_SYSMALLOC=ON). For more info, see
> > +          # root CMakeLists.txt.
> > +          -DLUAJIT_USE_SYSMALLOC=ON
> > +          # XXX: LUAJIT_USE_SYSMALLOC cannot be enabled on x64
> > +          # without GC64, since realloc usually doesn't return
> > +          # addresses in the right address range. For more info,
> > +          # see root CMakeLists.txt.
> > +          -DLUAJIT_ENABLE_GC64=ON
> Nit: I suppose it would be easy read paragraph above if indent it by "-S",
> not by "cmake".

We have such alignment in all workflow files. The idea is nice, but I
see no reason to touch it now. Ignoring.

> > +      - name: build
> > +        run: cmake --build . --parallel
> > +        working-directory: ${{ env.BUILDDIR }}
> > +      - name: test
> > +        env:
> > +          # Enable as much checks as possible. See more info here:
> > +          # https://github.com/google/sanitizers/wiki/AddressSanitizerFlags.
> > +          ASAN_OPTIONS: "                    \
> > +            detect_invalid_pointer_pairs=1:  \
> > +            detect_leaks=1:                  \
> > +            detect_stack_use_after_return=1: \
> > +            dump_instruction_bytes=1:        \
> > +            heap_profile=0:                  \
> > +            print_suppressions=0             \
> > +            symbolize=1:                     \
> > +            unmap_shadow_on_exit=1:          \
> > +          "
> 
> This options are used in CI and doesn't present in CMake, so ASAN will work
> different locally and in CI.
> 
> Is it expected?

As we discussed offline, it's not a trivial task to implement,
considering integration testing with Tarantool. Since, this is not a
popular configuration to be manually tested (until you poisoned the code
with a leak), I suggest to return to this later. From my side, I have
several ideas to try, so I'll share the results when I have some.

> 
> > +        run: cmake --build . --parallel --target LuaJIT-test
> > +        working-directory: ${{ env.BUILDDIR }}

-- 
Best regards,
IM

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 5/5] ci: introduce testing workflow with sanitizers
  2023-07-26 11:29   ` Sergey Kaplun via Tarantool-patches
@ 2023-07-26 16:35     ` Igor Munkin via Tarantool-patches
  0 siblings, 0 replies; 25+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2023-07-26 16:35 UTC (permalink / raw)
  To: Sergey Kaplun; +Cc: tarantool-patches

Sergey,

Thanks for your review!

On 26.07.23, Sergey Kaplun wrote:
> Hi, Igor!
> Thanks for the patch!
> The patch is generally LGTM, after fixing Sergey's comments. But I'm
> really concerned about the fact, that the CI don't show any error for
> lj-1024-* [1], lj-128-* [2] tests, where we have obvious memleak, since
> `os.exit()` is used instead of `test:done(true)` for these tests.

Thanks for noticing this! Unfortunately, it was a bug in CI description,
so the failures after rebasing were hidden. See the incremental patch
below:

================================================================================

diff --git a/.github/workflows/sanitizers-testing.yml b/.github/workflows/sanitizers-testing.yml
index 666ce6b2..28160ae3 100644
--- a/.github/workflows/sanitizers-testing.yml
+++ b/.github/workflows/sanitizers-testing.yml
@@ -51,22 +51,23 @@ jobs:
       - name: setup Linux for sanitizers
         uses: ./.github/actions/setup-sanitizers
       - name: configure
+        # XXX: LuaJIT configuration requires a couple of tweaks:
+        # LUAJIT_USE_SYSMALLOC=ON: Unfortunately, internal LuaJIT
+        #   memory allocator is not instrumented yet, so to find
+        #   any memory errors it's better to build LuaJIT with
+        #   system provided memory allocator (i.e. run CMake
+        #   configuration phase with -DLUAJIT_USE_SYSMALLOC=ON).
+        #   For more info, see root CMakeLists.txt.
+        # LUAJIT_ENABLE_GC64=ON: LUAJIT_USE_SYSMALLOC cannot be
+        #   enabled on x64 without GC64, since realloc usually
+        #   doesn't return addresses in the right address range.
+        #   For more info, see root CMakeLists.txt.
         run: >
           cmake -S . -B ${{ env.BUILDDIR }}
           -G Ninja
           ${{ matrix.CMAKEFLAGS }}
           -DLUAJIT_USE_ASAN=ON
-          # XXX: Unfortunately, internal LuaJIT memory allocator
-          # is not instrumented yet, so to find any memory errors
-          # it's better to build LuaJIT with system provided
-          # memory allocator (i.e. run CMake configuration phase
-          # with -DLUAJIT_USE_SYSMALLOC=ON). For more info, see
-          # root CMakeLists.txt.
           -DLUAJIT_USE_SYSMALLOC=ON
-          # XXX: LUAJIT_USE_SYSMALLOC cannot be enabled on x64
-          # without GC64, since realloc usually doesn't return
-          # addresses in the right address range. For more info,
-          # see root CMakeLists.txt.
           -DLUAJIT_ENABLE_GC64=ON
       - name: build
         run: cmake --build . --parallel


================================================================================

> 
> On 21.07.23, Igor Munkin wrote:
> > This commit adds GitHub workflow running all available LuaJIT tests with
> > LUAJIT_USE_ASAN option enabled. For now, sanitizers workflow works only
> > for Linux/x86_64 as the most scaling setup in our CI. I believe we will
> > be able to add other platforms being supported, when macOS runners
> > starvation is defeated. There is also a separate GitHub Action
> > introduced for convenient setup of the environment.
> > 
> > Besided, internal LuaJIT memory allocator is not instrumented yet
> 
> Typo? s/Besided/Besides/
> Typo: s/internal ... allocator/the internal ... allocator/

Fixed, thanks!

> 
> > unfortunately, so to find any memory faults it's better to build LuaJIT
> > with system provided memory allocator (i.e. run CMake configuration
> > phase with -DLUAJIT_USE_SYSMALLOC=ON). However, LUAJIT_USE_SYSMALLOC
> > cannot be enabled on x64 without GC64, since realloc usually doesn't
> > return addresses in the right address range. For more info, see root
> > CMakeLists.txt.
> > 
> > Follows up tarantool/tarantool#5878
> > 
> > Signed-off-by: Igor Munkin <imun@tarantool.org>
> > ---
> >  .github/actions/setup-sanitizers/README.md  | 12 +++
> >  .github/actions/setup-sanitizers/action.yml | 24 ++++++
> >  .github/workflows/sanitizers-testing.yml    | 89 +++++++++++++++++++++
> 
> <snipped>
> 
> > diff --git a/.github/actions/setup-sanitizers/action.yml b/.github/actions/setup-sanitizers/action.yml
> > new file mode 100644
> > index 00000000..ca6b6b9f
> > --- /dev/null
> > +++ b/.github/actions/setup-sanitizers/action.yml
> > @@ -0,0 +1,24 @@
> > +name: Setup CI environment for testing with sanitizers on Linux
> > +description: Common part to tweak Linux CI runner environment for sanitizers
> > +runs:
> > +  using: composite
> > +  steps:
> > +    - name: Setup CI environment
> > +      uses: ./.github/actions/setup
> > +    - name: Set CMAKE_BUILD_PARALLEL_LEVEL
> > +      run: |
> > +        # Set CMAKE_BUILD_PARALLEL_LEVEL environment variable to
> > +        # limit the number of parallel jobs for build/test step.
> > +        NPROC=$(nproc)
> > +        echo CMAKE_BUILD_PARALLEL_LEVEL=$(($NPROC + 1)) | tee -a $GITHUB_ENV
> > +      shell: bash
> > +    - name: Install build and test dependencies
> > +      run: |
> > +        apt -y update
> > +        apt -y install clang-11 cmake ninja-build make perl
> > +      shell: bash
> > +    - name: Set Clang as a default toolchain
> > +      run: |
> > +        echo CC=clang-11 | tee -a $GITHUB_ENV
> > +        echo CXX=clang++-11 | tee -a $GITHUB_ENV
> 
> Do we need clang++ for LuaJIT? Why?

Removed.

> 
> > +      shell: bash
> > diff --git a/.github/workflows/sanitizers-testing.yml b/.github/workflows/sanitizers-testing.yml
> > new file mode 100644
> > index 00000000..6c345108
> > --- /dev/null
> > +++ b/.github/workflows/sanitizers-testing.yml
> 
> <snipped>
> 
> > +      - name: configure
> > +        run: >
> > +          cmake -S . -B ${{ env.BUILDDIR }}
> > +          -G Ninja
> > +          ${{ matrix.CMAKEFLAGS }}
> > +          -DLUAJIT_USE_ASAN=ON
> > +          # XXX: Unfortunately, internal LuaJIT memory allocator
> > +          # is not instrumented yet, so to find any memory errors
> > +          # it's better to build LuaJIT with system provided
> > +          # memory allocator (i.e. run CMake configuration phase
> > +          # with -DLUAJIT_USE_SYSMALLOC=ON). For more info, see
> > +          # root CMakeLists.txt.
> > +          -DLUAJIT_USE_SYSMALLOC=ON
> > +          # XXX: LUAJIT_USE_SYSMALLOC cannot be enabled on x64
> > +          # without GC64, since realloc usually doesn't return
> > +          # addresses in the right address range. For more info,
> > +          # see root CMakeLists.txt.
> > +          -DLUAJIT_ENABLE_GC64=ON
> > +      - name: build
> > +        run: cmake --build . --parallel
> > +        working-directory: ${{ env.BUILDDIR }}
> > +      - name: test
> > +        env:
> > +          # Enable as much checks as possible. See more info here:
> > +          # https://github.com/google/sanitizers/wiki/AddressSanitizerFlags.
> 
> Please, also add the link to the [1], since heap_profile is common flag
> (same for print_suppressions). Also, it is disabled by default, why do
> we need to forcify it to false?

I explicitly disabled these particular options, to avoid their unexpected
enabling, since these options might slow or even break the tests. Besides,
these flags are also disabled in Tarantool, so its another attempt to be in
sync with that repo. BTW, added the link, you've mentioned:

================================================================================

diff --git a/.github/workflows/sanitizers-testing.yml b/.github/workflows/sanitizers-testing.yml
index 28160ae3..4bccfcef 100644
--- a/.github/workflows/sanitizers-testing.yml
+++ b/.github/workflows/sanitizers-testing.yml
@@ -75,7 +75,8 @@ jobs:
       - name: test
         env:
           # Enable as much checks as possible. See more info here:
-          # https://github.com/google/sanitizers/wiki/AddressSanitizerFlags.
+          # https://github.com/google/sanitizers/wiki/AddressSanitizerFlags,
+          # https://github.com/google/sanitizers/wiki/SanitizerCommonFlags.
           ASAN_OPTIONS: "                    \
             detect_invalid_pointer_pairs=1:  \
             detect_leaks=1:                  \

================================================================================

> 
> > +          ASAN_OPTIONS: "                    \
> > +            detect_invalid_pointer_pairs=1:  \
> > +            detect_leaks=1:                  \
> > +            detect_stack_use_after_return=1: \
> > +            dump_instruction_bytes=1:        \
> > +            heap_profile=0:                  \
> > +            print_suppressions=0             \

Also fixed a typo here:

================================================================================

diff --git a/.github/workflows/sanitizers-testing.yml b/.github/workflows/sanitizers-testing.yml
index 6c345108..666ce6b2 100644
--- a/.github/workflows/sanitizers-testing.yml
+++ b/.github/workflows/sanitizers-testing.yml
@@ -81,7 +81,7 @@ jobs:
             detect_stack_use_after_return=1: \
             dump_instruction_bytes=1:        \
             heap_profile=0:                  \
-            print_suppressions=0             \
+            print_suppressions=0:            \
             symbolize=1:                     \
             unmap_shadow_on_exit=1:          \
           "

================================================================================

> > +            symbolize=1:                     \
> > +            unmap_shadow_on_exit=1:          \
> > +          "
> > +        run: cmake --build . --parallel --target LuaJIT-test
> > +        working-directory: ${{ env.BUILDDIR }}
> > -- 
> > 2.30.2
> > 
> 
> [1]: https://github.com/tarantool/luajit/actions/runs/5619185186/job/15225900726#step:6:673
> [2]: https://github.com/tarantool/luajit/actions/runs/5619185186/job/15225900726#step:6:638
> [3]: https://github.com/google/sanitizers/wiki/SanitizerCommonFlags
> 
> -- 
> Best regards,
> Sergey Kaplun

-- 
Best regards,
IM

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 4/5] build: introduce LUAJIT_USE_ASAN option
  2023-07-26 12:54     ` Igor Munkin via Tarantool-patches
@ 2023-07-27 11:06       ` Sergey Bronnikov via Tarantool-patches
  0 siblings, 0 replies; 25+ messages in thread
From: Sergey Bronnikov via Tarantool-patches @ 2023-07-27 11:06 UTC (permalink / raw)
  To: Igor Munkin; +Cc: tarantool-patches

Hi, Igor


LGTM now


On 7/26/23 15:54, Igor Munkin wrote:
> Sergey,
>
> Thanks for your review! Please consider my answer inline (though, we've
> already discussed it offline).
>
> On 25.07.23, Sergey Bronnikov wrote:
>> Hello, again
>>
>>
>> On 7/21/23 11:12, Igor Munkin wrote:
>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 5/5] ci: introduce testing workflow with sanitizers
  2023-07-26 14:53     ` Igor Munkin via Tarantool-patches
@ 2023-07-27 11:13       ` Sergey Bronnikov via Tarantool-patches
  0 siblings, 0 replies; 25+ messages in thread
From: Sergey Bronnikov via Tarantool-patches @ 2023-07-27 11:13 UTC (permalink / raw)
  To: Igor Munkin; +Cc: tarantool-patches

Hi, Igor!

LGTM

On 7/26/23 17:53, Igor Munkin wrote:
> Sergey,
>
> Thanks for your review! See my answers inline.
>
> On 24.07.23, Sergey Bronnikov wrote:
>> Thanks for the patch!
>>
>> See my comments below.
>>
>>
>> Sergey
>>
>> On 7/21/23 11:12, Igor Munkin wrote:
>>
>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [Tarantool-patches] [PATCH luajit v2 0/5] Add ASan support in LuaJIT
  2023-07-21  8:12 [Tarantool-patches] [PATCH luajit v2 0/5] Add ASan support in LuaJIT Igor Munkin via Tarantool-patches
                   ` (4 preceding siblings ...)
  2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 5/5] ci: introduce testing workflow with sanitizers Igor Munkin via Tarantool-patches
@ 2023-08-03  7:31 ` Igor Munkin via Tarantool-patches
  5 siblings, 0 replies; 25+ messages in thread
From: Igor Munkin via Tarantool-patches @ 2023-08-03  7:31 UTC (permalink / raw)
  To: Sergey Kaplun, Sergey Bronnikov; +Cc: tarantool-patches

Pals, thanks for your reviews!

I've checked the patchset into all long-term branches in
tarantool/luajit and bumped a new version in master, release/2.11 and
release/2.10.

On 21.07.23, Igor Munkin wrote:
> This series implements the second attempt to enable ASan support back
> for LuaJIT repository.
> 
> The only thing that was missing the whole time was the option per se
> (and the corresponding compile flags, obviously). Anyway, when the
> option has been finally added, the dedicated CI workflow has been added
> too in scope of the second patch in the series. All other info can be
> found in the corresponding patches.
> 
> Besided, internal LuaJIT memory allocator is not instrumented yet
> unfortunately, so to find any memory faults it's better to build LuaJIT
> with system provided memory allocator (i.e. run CMake configuration
> phase with -DLUAJIT_USE_SYSMALLOC=ON). However, LUAJIT_USE_SYSMALLOC
> cannot be enabled on x64 without GC64, since realloc usually doesn't
> return addresses in the right address range. For more info, see root
> CMakeLists.txt.
> 
> Surprisingly, some hidden bugs were found while testing the
> aforementioned configuration.
> 
> 1. The assertions in memprof initialization, checking the state of the
> allocator against NULL, can fail if this allocator requires no internal
> state (e.g. glibc functions for allocating dynamic memory). In fact,
> when building LuaJIT with LUAJIT_USE_SYSMALLOC option enabled, NULL is
> given as the second parameter to <lua_newstate> and these assertions
> fail as a result. Hence, they are simply removed.
> 
> 2. Before the patch all tests in tarantool-tests suite (except
> <lj-603-err-snap-restore.test.lua>) terminate their execution via
> <os.exit> with the status depending on the test results. However, the
> second argument of <os.exit> was omitted and Lua universe was not
> properly finalized as a result. This behaviour becomes a problem, when
> LuaJIT is build with LUAJIT_USE_SYSMALLOC option and AddressSanitizer
> support enabled, since the sanitizer starts reporting false positive
> errors about the memory allocations without the corresponding memory
> releases. To resolve these errors, the second parameter to each
> <os.exit> call terminating the test has to be added. To avoid loss of
> the aforementioned parameter in future, <test:done> helper has been
> added to the TAP module. Depending on the single parameter, the new
> helper either properly finalize the test being run, or simply checks all
> the test assertions and raises an error if any of them fail. The latter
> case is added especially to handle <lj-603-err-snap-restore.test.lua>
> specifics and still check that everything works fine.
> 
> 
> Last but not least: for all ARM64 jobs in exotic builds testing pipeline
> non-GC64 configurations were disabled, since LUAJIT_ENABLE_GC64 takes no
> effect for this arch (GC64 is the only option).
> 
> Issue: https://github.com/tarantool/tarantool/issues/5878
> Branch: https://github.com/tarantool/luajit/tree/hackaton/gh-5878-enable-ASAN
> Tarantool related changes and CI can be found in #8846[1].
> 
> v1: https://lists.tarantool.org/tarantool-patches/cover.1689195028.git.imun@tarantool.org/T/#t
> 
> Changes in v2:
>   * Fixed comments as per review by Sergey B. and Sergey K
>   * Enabled LUAJIT_USE_SYSMALLOC option in sanitizers-testing.yml
>   * Removed two invalid assertions in memprof sources (found via
>     enabling LUAJIT_USE_SYSMALLOC option)
>   * Introduced test:done helper for proper test finalization (found via
>     enabling both LUAJIT_USE_ASAN and LUAJIT_USE_SYSMALLOC)
>   * Little maintenance of exotic builds workflow
> 
> Igor Munkin (5):
>   ci: clean up workflow for exotic builds
>   memprof: remove invalid assertions
>   test: introduce test:done TAP helper
>   build: introduce LUAJIT_USE_ASAN option
>   ci: introduce testing workflow with sanitizers
> 

<snipped>

> 
> [1]: https://github.com/tarantool/tarantool/pull/8846
> 
> -- 
> 2.30.2
> 

-- 
Best regards,
IM

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2023-08-03  7:51 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-21  8:12 [Tarantool-patches] [PATCH luajit v2 0/5] Add ASan support in LuaJIT Igor Munkin via Tarantool-patches
2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 1/5] ci: clean up workflow for exotic builds Igor Munkin via Tarantool-patches
2023-07-24 10:36   ` Sergey Bronnikov via Tarantool-patches
2023-07-26  9:37   ` Sergey Kaplun via Tarantool-patches
2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 2/5] memprof: remove invalid assertions Igor Munkin via Tarantool-patches
2023-07-24 10:46   ` Sergey Bronnikov via Tarantool-patches
2023-07-26  9:41   ` Sergey Kaplun via Tarantool-patches
2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 3/5] test: introduce test:done TAP helper Igor Munkin via Tarantool-patches
2023-07-24 10:53   ` Sergey Bronnikov via Tarantool-patches
2023-07-26 10:43   ` Sergey Kaplun via Tarantool-patches
2023-07-26 12:42     ` Igor Munkin via Tarantool-patches
2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 4/5] build: introduce LUAJIT_USE_ASAN option Igor Munkin via Tarantool-patches
2023-07-24 11:41   ` Sergey Bronnikov via Tarantool-patches
2023-07-26 13:06     ` Igor Munkin via Tarantool-patches
2023-07-25 12:26   ` Sergey Bronnikov via Tarantool-patches
2023-07-26 12:54     ` Igor Munkin via Tarantool-patches
2023-07-27 11:06       ` Sergey Bronnikov via Tarantool-patches
2023-07-26 11:03   ` Sergey Kaplun via Tarantool-patches
2023-07-21  8:12 ` [Tarantool-patches] [PATCH luajit v2 5/5] ci: introduce testing workflow with sanitizers Igor Munkin via Tarantool-patches
2023-07-24 11:54   ` Sergey Bronnikov via Tarantool-patches
2023-07-26 14:53     ` Igor Munkin via Tarantool-patches
2023-07-27 11:13       ` Sergey Bronnikov via Tarantool-patches
2023-07-26 11:29   ` Sergey Kaplun via Tarantool-patches
2023-07-26 16:35     ` Igor Munkin via Tarantool-patches
2023-08-03  7:31 ` [Tarantool-patches] [PATCH luajit v2 0/5] Add ASan support in LuaJIT Igor Munkin via Tarantool-patches

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox