[#1] mclock: Fix possible deadlock
There is a possible call-chain `scheduleRequest()` -> `runAt()` -> `scheduleRequest()`, so second `scheduleRequest()` may be locked on mutext held by first `scheduleRequest()`. Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
parent
f1cb5b40d5
commit
d8663f1a74
1 changed files with 10 additions and 7 deletions
|
@ -36,7 +36,10 @@ func (c *systemClock) now() float64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *systemClock) runAt(ts float64, f func()) {
|
func (c *systemClock) runAt(ts float64, f func()) {
|
||||||
c.schedule <- scheduleInfo{ts: ts, f: f}
|
select {
|
||||||
|
case c.schedule <- scheduleInfo{ts: ts, f: f}:
|
||||||
|
default: // timer fired, scheduleRequest will call runAt again
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *systemClock) close() {
|
func (c *systemClock) close() {
|
||||||
|
@ -48,7 +51,8 @@ func (c *systemClock) start() {
|
||||||
c.wg.Add(1)
|
c.wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer c.wg.Done()
|
defer c.wg.Done()
|
||||||
t := time.NewTimer(time.Hour)
|
t := time.NewTimer(0)
|
||||||
|
<-t.C
|
||||||
var f func()
|
var f func()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
@ -61,11 +65,10 @@ func (c *systemClock) start() {
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var d time.Duration
|
||||||
now := c.now()
|
now := c.now()
|
||||||
if now >= s.ts {
|
if now < s.ts {
|
||||||
s.f()
|
d = time.Duration((s.ts - now) * 1e9)
|
||||||
f = nil
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
if !t.Stop() {
|
if !t.Stop() {
|
||||||
select {
|
select {
|
||||||
|
@ -73,7 +76,7 @@ func (c *systemClock) start() {
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.Reset(time.Duration((s.ts - now) * 1e9))
|
t.Reset(d)
|
||||||
f = s.f
|
f = s.f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue