From 86a184ad27d9948bf6248752e4f9b7e118fb3688 Mon Sep 17 00:00:00 2001 From: Arnaud Mimart <33665250+amimart@users.noreply.github.com> Date: Mon, 20 Mar 2023 23:08:37 +0100 Subject: [PATCH] fix(logic): avoid killing querying goroutine on gas limit exceeded --- x/logic/keeper/grpc_query_ask.go | 7 ------- x/logic/keeper/interpreter.go | 4 ++++ x/logic/meter/safe.go | 15 --------------- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/x/logic/keeper/grpc_query_ask.go b/x/logic/keeper/grpc_query_ask.go index 0e239184..82803419 100644 --- a/x/logic/keeper/grpc_query_ask.go +++ b/x/logic/keeper/grpc_query_ask.go @@ -34,13 +34,6 @@ func (k Keeper) Ask(ctx goctx.Context, req *types.QueryServiceAskRequest) (respo panic(r) } - if sdkCtx.GasMeter().IsOutOfGas() { - response, err = nil, sdkerrors.Wrapf( - types.LimitExceeded, "out of gas: %s (%d/%d)", - types.ModuleName, sdkCtx.GasMeter().GasConsumed(), sdkCtx.GasMeter().Limit()) - - return - } }() sdkCtx.GasMeter().ConsumeGas(sdkCtx.GasMeter().GasConsumed(), types.ModuleName) diff --git a/x/logic/keeper/interpreter.go b/x/logic/keeper/interpreter.go index 5d81fc14..b7b29b5f 100644 --- a/x/logic/keeper/interpreter.go +++ b/x/logic/keeper/interpreter.go @@ -73,6 +73,10 @@ func (k Keeper) execute(ctx goctx.Context, program, query string) (*types.QueryS results = append(results, types.Result{Substitutions: m.ToSubstitutions()}) } + if sols.Err() != nil && sdkCtx.GasMeter().IsOutOfGas() { + panic(sdk.ErrorOutOfGas{Descriptor: "Prolog interpreter execution"}) + } + return &types.QueryServiceAskResponse{ Height: uint64(sdkCtx.BlockHeight()), GasUsed: sdkCtx.GasMeter().GasConsumed(), diff --git a/x/logic/meter/safe.go b/x/logic/meter/safe.go index d2317348..1dee7806 100644 --- a/x/logic/meter/safe.go +++ b/x/logic/meter/safe.go @@ -1,7 +1,6 @@ package meter import ( - "runtime" "sync" sdk "github.com/cosmos/cosmos-sdk/types" @@ -25,20 +24,6 @@ func WithSafeMeter(gasMeter sdk.GasMeter) sdk.GasMeter { // ConsumeGas consumes the given amount of gas from the decorated gas meter. func (m *safeMeterDecorater) ConsumeGas(amount uint64, descriptor string) { m.mutex.Lock() - defer func() { - if r := recover(); r != nil { - if _, ok := r.(sdk.ErrorOutOfGas); ok { - // Since predicate is called into a goroutine, when out of gas is thrown, the main caller - // (grpc: https://github.com/okp4/okp4d/blob/main/x/logic/keeper/grpc_query_ask.go#L25-L36, or querier) - // cannot recover ErrOutOfGas. To avoid the chain panicking, we need to exit without panic. - // Goexit runs all deferred calls before terminating the goroutine. Because Goexit - // is not a panic, any recover calls in those deferred functions will return nil. - // This is a temporary solution before implementing a context cancellation. - runtime.Goexit() - } - panic(r) - } - }() defer m.mutex.Unlock() m.gasMeter.ConsumeGas(amount, descriptor)