From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 6E8E25FC8F9; Fri, 29 Sep 2023 09:22:53 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 6E8E25FC8F9 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1695968573; bh=p0A2bJDm0+OTGbEzM8YaAn/YYlC3fOaSO4xX4tzrTPU=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=wLT1ENmfzxkMkEQOaBlCxPRclkRs+yZ1iX9f0XjGQIqTHJ5mvNlRIgRYxRkzqF8vc R7axITY0yMMk448Zzv1mw8Cxg2q4GSRvINqGnX1FL6N5Sk0AVy1NPNPIkPgbZScynJ dJbc7QW30oT++uAfWo5ACpsMy25VH1nmgiQWkV1Q= Received: from mail-lf1-f52.google.com (mail-lf1-f52.google.com [209.85.167.52]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id C416E5FC8F9 for ; Fri, 29 Sep 2023 09:20:33 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org C416E5FC8F9 Received: by mail-lf1-f52.google.com with SMTP id 2adb3069b0e04-5044dd5b561so16487255e87.1 for ; Thu, 28 Sep 2023 23:20:33 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695968433; x=1696573233; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=kVctt9HfFSjkRx+j3fAfRYshpsa2EmBPP2dKRws2di8=; b=K5L/1odz6JPQOyg1c+MrZ18bgAWy3wE1YyFrg9jxG2lTbrVAKy20uXpi4zoIT8jogD UTvWztNbbaW1nm5SSFu0AMsIr401ifV8Nzl7dQlTSczeNanZeRPeABoBvF0eyneHh1bP iOo15rvE0Dkdz1eANw+con/PTatZXXDkSyrAKX4umT6M3rYr+pwQlDmd99ML0IqCTJem 5z3aN2xY5xEoZ8M9SeeEtNuPxDk5phHTY4IAtWOeE8D0YpWffDUCdF0woRR7mQsFQziW ui3aj6H6AbLTcrVraZEhhqZRSSBluHw/nhmBnxnplZzlbZDstBzfVdxssL3Tyo0fAy76 /qVg== X-Gm-Message-State: AOJu0YwXErcGKOUa8ThXMpOVBhLaRkhS0oskw9d98DgcU88SXyPIpjdt vmJju1YavLZdaXJphvO0SCTlL2It5EI= X-Google-Smtp-Source: AGHT+IHp+GTvWOLkRCAKyebCaP+cVPpOlcYywoOcpc04NOydsZzx+Lik8FTzZzTTFNgygWpvrDUd8A== X-Received: by 2002:a05:6512:485a:b0:503:90d:e0df with SMTP id ep26-20020a056512485a00b00503090de0dfmr2672033lfb.34.1695968432596; Thu, 28 Sep 2023 23:20:32 -0700 (PDT) Received: from localhost.localdomain ([93.175.28.59]) by smtp.gmail.com with ESMTPSA id c14-20020a056512238e00b0050485bad4b4sm917717lfv.222.2023.09.28.23.20.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 23:20:32 -0700 (PDT) X-Google-Original-From: Maxim Kokryashkin To: tarantool-patches@dev.tarantool.org, skaplun@tarantool.org, sergeyb@tarantool.org Date: Fri, 29 Sep 2023 09:20:14 +0300 Message-ID: <839195a6a6ff32a49c5a690a9f0101cc741901fd.1695968227.git.m.kokryashkin@tarantool.org> X-Mailer: git-send-email 2.42.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [Tarantool-patches] [PATCH luajit v2 5/5] Restore cur_L for specific Lua/C API use case. X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Maxim Kokryashkin via Tarantool-patches Reply-To: Maxim Kokryashkin Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" From: Mike Pall Thanks to Peter Cawley. (cherry-picked from commit e86990f7f24a94b0897061f25a84547fe1108bed) Consider the following Lua C API function: ``` static int error_after_coroutine_return(lua_State *L) { lua_State *innerL = lua_newthread(L); luaL_loadstring(innerL, "print('inner coro')"); lua_pcall(innerL, 0, 0, 0); luaL_error(L, "my fancy error"); return 0; } ``` And the following Lua script: ``` local libcur_L = require('libcur_L') local function onesnap_f(var) if var then return 1 else return 0 end end -- Compile function to trace with snapshot. if jit then jit.opt.start('hotloop=1') end onesnap_f(true) onesnap_f(true) local r, s = pcall(libcur_L.error_after_coroutine_return) onesnap_f(false) ``` This is the only case when `cur_L` is not restored, according to the analysis done in https://github.com/LuaJIT/LuaJIT/issues/1066. This patch changes the error-catching routine, so now the patch sets the actual cur_L there. Now it is possible to throw errors on non-executing coroutines, which is a violation of the Lua C API. So, even though it is now possible, that behavior should be avoided anyway. Maxim Kokryashkin: * added the description and the test for the problem Resolves tarantool/tarantool#6323 --- src/lj_err.c | 5 ++- test/tarantool-tests/CMakeLists.txt | 1 + ...-fix-cur_L-after-coroutine-resume.test.lua | 32 +++++++++++++++++++ .../CMakeLists.txt | 1 + .../libcur_L_coroutine.c | 22 +++++++++++++ 5 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 test/tarantool-tests/lj-1066-fix-cur_L-after-coroutine-resume.test.lua create mode 100644 test/tarantool-tests/lj-1066-fix-cur_L-after-coroutine-resume/CMakeLists.txt create mode 100644 test/tarantool-tests/lj-1066-fix-cur_L-after-coroutine-resume/libcur_L_coroutine.c diff --git a/src/lj_err.c b/src/lj_err.c index 46fb81ee..1a9a2f2b 100644 --- a/src/lj_err.c +++ b/src/lj_err.c @@ -174,12 +174,15 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) case FRAME_PCALL: /* FF pcall() frame. */ case FRAME_PCALLH: /* FF pcall() frame inside hook. */ if (errcode) { + global_State *g; if (errcode == LUA_YIELD) { frame = frame_prevd(frame); break; } + g = G(L); + setgcref(g->cur_L, obj2gco(L)); if (frame_typep(frame) == FRAME_PCALL) - hook_leave(G(L)); + hook_leave(g); L->base = frame_prevd(frame) + 1; L->cframe = cf; unwindstack(L, L->base); diff --git a/test/tarantool-tests/CMakeLists.txt b/test/tarantool-tests/CMakeLists.txt index c15d6037..d84072e0 100644 --- a/test/tarantool-tests/CMakeLists.txt +++ b/test/tarantool-tests/CMakeLists.txt @@ -68,6 +68,7 @@ add_subdirectory(lj-727-lightuserdata-itern) add_subdirectory(lj-802-panic-at-mcode-protfail) add_subdirectory(lj-flush-on-trace) add_subdirectory(lj-1004-oom-error-frame) +add_subdirectory(lj-1066-fix-cur_L-after-coroutine-resume) # The part of the memory profiler toolchain is located in tools # directory, jit, profiler, and bytecode toolchains are located diff --git a/test/tarantool-tests/lj-1066-fix-cur_L-after-coroutine-resume.test.lua b/test/tarantool-tests/lj-1066-fix-cur_L-after-coroutine-resume.test.lua new file mode 100644 index 00000000..3919ae23 --- /dev/null +++ b/test/tarantool-tests/lj-1066-fix-cur_L-after-coroutine-resume.test.lua @@ -0,0 +1,32 @@ +local tap = require('tap') +local test = tap.test('lj-1066-fix-cur_L-after-coroutine-resume'):skipcond({ + ['Test requires JIT enabled'] = not jit.status(), +}) + +test:plan(1) + +local libcur_L_coroutine = require('libcur_L_coroutine') + +local function cbool(cond) + if cond then + return 1 + else + return 0 + end +end + +-- Compile function to trace with snapshot. +jit.opt.start('hotloop=1') +-- First call makes `cbool()` hot enough to be recorded next time. +cbool(true) +-- Second call records `cbool()` body (i.e. `if` branch). This is +-- a root trace for `cbool()`. +cbool(true) + +local res = pcall(libcur_L_coroutine.error_after_coroutine_return) +assert(res == false, "return from error") +-- Call with restoration from a snapshot with wrong cur_L. +cbool(false) + +test:ok(true) +test:done(true) diff --git a/test/tarantool-tests/lj-1066-fix-cur_L-after-coroutine-resume/CMakeLists.txt b/test/tarantool-tests/lj-1066-fix-cur_L-after-coroutine-resume/CMakeLists.txt new file mode 100644 index 00000000..c8a3731f --- /dev/null +++ b/test/tarantool-tests/lj-1066-fix-cur_L-after-coroutine-resume/CMakeLists.txt @@ -0,0 +1 @@ +BuildTestCLib(libcur_L_coroutine libcur_L_coroutine.c) diff --git a/test/tarantool-tests/lj-1066-fix-cur_L-after-coroutine-resume/libcur_L_coroutine.c b/test/tarantool-tests/lj-1066-fix-cur_L-after-coroutine-resume/libcur_L_coroutine.c new file mode 100644 index 00000000..7a71d0f0 --- /dev/null +++ b/test/tarantool-tests/lj-1066-fix-cur_L-after-coroutine-resume/libcur_L_coroutine.c @@ -0,0 +1,22 @@ +#include "lua.h" +#include "lauxlib.h" + +static int error_after_coroutine_return(lua_State *L) +{ + lua_State *innerL = lua_newthread(L); + luaL_loadstring(innerL, "print('inner coro')"); + lua_pcall(innerL, 0, 0, 0); + luaL_error(L, "my fancy error"); + return 0; +} + +static const struct luaL_Reg libcur_L_coroutine[] = { + {"error_after_coroutine_return", error_after_coroutine_return}, + {NULL, NULL} +}; + +LUA_API int luaopen_libcur_L_coroutine(lua_State *L) +{ + luaL_register(L, "libcur_L_coroutine", libcur_L_coroutine); + return 1; +} -- 2.42.0