fix(executors): periodicalexecutor should handle crash correctly (#3043)

master
cong 2 years ago committed by GitHub
parent a561048d59
commit 18d163c4f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -116,7 +116,7 @@ func (pe *PeriodicalExecutor) addAndCheck(task any) (any, bool) {
} }
func (pe *PeriodicalExecutor) backgroundFlush() { func (pe *PeriodicalExecutor) backgroundFlush() {
threading.GoSafe(func() { go func() {
// flush before quit goroutine to avoid missing tasks // flush before quit goroutine to avoid missing tasks
defer pe.Flush() defer pe.Flush()
@ -144,7 +144,7 @@ func (pe *PeriodicalExecutor) backgroundFlush() {
} }
} }
} }
}) }()
} }
func (pe *PeriodicalExecutor) doneExecution() { func (pe *PeriodicalExecutor) doneExecution() {
@ -162,7 +162,9 @@ func (pe *PeriodicalExecutor) executeTasks(tasks any) bool {
ok := pe.hasTasks(tasks) ok := pe.hasTasks(tasks)
if ok { if ok {
pe.container.Execute(tasks) threading.RunSafe(func() {
pe.container.Execute(tasks)
})
} }
return ok return ok

@ -108,6 +108,64 @@ func TestPeriodicalExecutor_Bulk(t *testing.T) {
lock.Unlock() lock.Unlock()
} }
func TestPeriodicalExecutor_Panic(t *testing.T) {
// avoid data race
var lock sync.Mutex
ticker := timex.NewFakeTicker()
var (
executedTasks []int
expected []int
)
executor := NewPeriodicalExecutor(time.Millisecond, newContainer(time.Millisecond, func(tasks any) {
tt := tasks.([]int)
lock.Lock()
executedTasks = append(executedTasks, tt...)
lock.Unlock()
if tt[0] == 0 {
panic("test")
}
}))
executor.newTicker = func(duration time.Duration) timex.Ticker {
return ticker
}
for i := 0; i < 30; i++ {
executor.Add(i)
expected = append(expected, i)
}
ticker.Tick()
ticker.Tick()
time.Sleep(time.Millisecond)
lock.Lock()
assert.Equal(t, expected, executedTasks)
lock.Unlock()
}
func TestPeriodicalExecutor_FlushPanic(t *testing.T) {
var (
executedTasks []int
expected []int
lock sync.Mutex
)
executor := NewPeriodicalExecutor(time.Millisecond, newContainer(time.Millisecond, func(tasks any) {
tt := tasks.([]int)
lock.Lock()
executedTasks = append(executedTasks, tt...)
lock.Unlock()
if tt[0] == 0 {
panic("flush panic")
}
}))
for i := 0; i < 8; i++ {
executor.Add(i)
expected = append(expected, i)
}
executor.Flush()
lock.Lock()
assert.Equal(t, expected, executedTasks)
lock.Unlock()
}
func TestPeriodicalExecutor_Wait(t *testing.T) { func TestPeriodicalExecutor_Wait(t *testing.T) {
var lock sync.Mutex var lock sync.Mutex
executer := NewBulkExecutor(func(tasks []any) { executer := NewBulkExecutor(func(tasks []any) {
@ -151,13 +209,7 @@ func TestPeriodicalExecutor_Deadlock(t *testing.T) {
} }
func TestPeriodicalExecutor_hasTasks(t *testing.T) { func TestPeriodicalExecutor_hasTasks(t *testing.T) {
ticker := timex.NewFakeTicker()
defer ticker.Stop()
exec := NewPeriodicalExecutor(time.Millisecond, newContainer(time.Millisecond, nil)) exec := NewPeriodicalExecutor(time.Millisecond, newContainer(time.Millisecond, nil))
exec.newTicker = func(d time.Duration) timex.Ticker {
return ticker
}
assert.False(t, exec.hasTasks(nil)) assert.False(t, exec.hasTasks(nil))
assert.True(t, exec.hasTasks(1)) assert.True(t, exec.hasTasks(1))
} }

Loading…
Cancel
Save