Skip to content

Commit

Permalink
fix(machine): fix Dispose() deadlock (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
pancsta committed Jul 10, 2024
1 parent 02fcb0d commit cdab12a
Showing 1 changed file with 15 additions and 13 deletions.
28 changes: 15 additions & 13 deletions pkg/machine/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ type Machine struct {
queueRunning bool

emitters []*emitter
once sync.Once
clock Clocks
cancel context.CancelFunc
logLevel LogLevel
Expand Down Expand Up @@ -291,36 +290,39 @@ func cloneOptions(opts *Opts) *Opts {
func (m *Machine) Dispose() {
// dispose in a goroutine to avoid a deadlock when called from within a
// handler
if m.Disposed {
return
}

go func() {
if m.Disposed {
return
}
m.queueProcessing.Lock()
m.unlockDisposed = true
m.once.Do(m.dispose)
m.dispose(false)
}()
}

// DisposeForce disposes the machine and all its emitters, without waiting for
// the queue to drain. Will cause panics.
func (m *Machine) DisposeForce() {
m.once.Do(m.dispose)
m.dispose(true)
}

func (m *Machine) dispose() {
func (m *Machine) dispose(force bool) {
m.Disposed = true

for i := range m.Tracers {
m.Tracers[i].MachineDispose(m.ID)
}

m.activeStatesLock.Lock()
defer m.activeStatesLock.Unlock()
m.indexWhenArgsLock.Lock()
defer m.indexWhenArgsLock.Unlock()
m.indexEventChLock.Lock()
defer m.indexEventChLock.Unlock()
// skip the locks when forcing
if !force {
m.activeStatesLock.Lock()
defer m.activeStatesLock.Unlock()
m.indexWhenArgsLock.Lock()
defer m.indexWhenArgsLock.Unlock()
m.indexEventChLock.Lock()
defer m.indexEventChLock.Unlock()
}

m.log(LogEverything, "[end] dispose")
m.cancel()
Expand Down

0 comments on commit cdab12a

Please sign in to comment.