Fix tracer race condition

This commit is contained in:
Tony Chen 2025-07-23 14:08:29 +08:00
parent bb62a288aa
commit 02460a34cd

View file

@ -1054,6 +1054,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb vm.StateDB, config *TraceConfig, precompiles vm.PrecompiledContracts) (value interface{}, returnErr error) { func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb vm.StateDB, config *TraceConfig, precompiles vm.PrecompiledContracts) (value interface{}, returnErr error) {
var ( var (
tracer *Tracer tracer *Tracer
tracerMtx *sync.Mutex
err error err error
timeout = defaultTraceTimeout timeout = defaultTraceTimeout
usedGas uint64 usedGas uint64
@ -1082,6 +1083,7 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
} }
} }
tracingStateDB := state.NewHookedState(statedb, tracer.Hooks) tracingStateDB := state.NewHookedState(statedb, tracer.Hooks)
tracerMtx = &sync.Mutex{}
txCtx := core.NewEVMTxContext(message) txCtx := core.NewEVMTxContext(message)
evm := vm.NewEVM(vmctx, tracingStateDB, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true}, api.backend.GetCustomPrecompiles(vmctx.BlockNumber.Int64())) evm := vm.NewEVM(vmctx, tracingStateDB, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true}, api.backend.GetCustomPrecompiles(vmctx.BlockNumber.Int64()))
if precompiles != nil { if precompiles != nil {
@ -1099,7 +1101,9 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
go func() { go func() {
<-deadlineCtx.Done() <-deadlineCtx.Done()
if errors.Is(deadlineCtx.Err(), context.DeadlineExceeded) { if errors.Is(deadlineCtx.Err(), context.DeadlineExceeded) {
tracerMtx.Lock()
tracer.Stop(errors.New("execution timeout")) tracer.Stop(errors.New("execution timeout"))
tracerMtx.Unlock()
// Stop evm execution. Note cancellation is not necessarily immediate. // Stop evm execution. Note cancellation is not necessarily immediate.
evm.Cancel() evm.Cancel()
} }
@ -1119,7 +1123,10 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
} }
return nil, fmt.Errorf("tracing failed: %w", err) return nil, fmt.Errorf("tracing failed: %w", err)
} }
return tracer.GetResult() tracerMtx.Lock()
res, err := tracer.GetResult()
tracerMtx.Unlock()
return res, err
} }
// APIs return the collection of RPC services the tracer package offers. // APIs return the collection of RPC services the tracer package offers.