Repository navigation
pipeline panic #208
Description
Activity
Hello @derekperkins,
I couldn't manage to reproduce the problem. It's very likely there is a nil item in the list of commands.
pipecannot be nil. I reviewed the code. I couldn't find any reason for nil commands. There can be a subtle bug in the command pool logic. Do you useDiscard?func (dp *DMapPipeline) execOnPartition(ctx context.Context, partID uint64) error { rc, err := dp.dm.clusterClient.clientByPartID(partID) if err != nil { return err } // There is no need to protect dp.commands map and its content. // It's already filled before running Exec, and it's now a read-only // data structure commands := dp.commands[partID] pipe := rc.Pipeline() for _, cmd := range commands { pipe.Do(ctx, cmd.Args()...) --> panics }
Could you share a code snippet to reproduce the problem?
Here is my hypothesis:
execOnPartitionassumes thatdp.commandsis read-only during the execution. Neitherdp.commandsnor its content is protected by a mutex during the execution. If your code callsExecandDiscardsimultaneously,execOnPartitionmay encounter nil items indp.commands.Discardcallsdp.closedCancel()at line 548, ifExecis already passed the context check at line 503, they can start running parallel.Yes, we're using Discard and reusing pipelines, but we're not calling Exec and Discard simultaneously on our own accord. This is simplified, but basically this is what we're doing.
defer pipeline.Discard() pipeline.Exec(ctx) for _, futureGet := range futureGets { futureGet.Result().Scan() }
I'm wondering if there's a race condition when context is canceled...
I'm wondering if there's a race condition when context is canceled...
I believe the possible root cause is this.
Same issue as #256 - linking for ref.
I believe it is indeed context cancellation.
Exec is synchronous except for https://github.com/buraksezer/olric/blob/6ca0e20256e0bd773dcfbbea7933eaa0f05a2f50/pipeline.go#L522-L525So context can be cancelled leading to Exec exiting while execOnPartition is still running.
I don't think this is a great behavior, think it'd be better to maintain sync aspect of Exec by either waiting here:
err := sem.Acquire(ctx, 1) if err != nil { // Wait for goroutines to complete _ = errGr.Wait() return err }
or alternatively handling cancellation in execOnPartition
This has panicked a couple times in the last hour or so running in prod