Skip to content

Instantly share code, notes, and snippets.

@enobufs
Created October 18, 2019 23:07
Show Gist options
  • Save enobufs/1019a5a8cc33201b6b0961a12b961152 to your computer and use it in GitHub Desktop.
Save enobufs/1019a5a8cc33201b6b0961a12b961152 to your computer and use it in GitHub Desktop.
Cgo deadlock with C.usleep()
package main
/*
#include <unistd.h>
*/
import "C"
import (
"log"
"time"
)
// TaskMgr ...
type TaskMgr struct {
NumRoutines int
Count int
Interval time.Duration
done []chan struct{}
}
// Start ...
func (t *TaskMgr) Start() error {
t.done = make([]chan struct{}, t.NumRoutines)
for i := 0; i < t.NumRoutines; i++ {
t.done[i] = make(chan struct{}, 1)
go func(taskID, count int, interval time.Duration, done chan<- struct{}) {
for j := 0; j < count; j++ {
//log.Printf("task %d: count %d", taskID, j)
time.Sleep(interval)
}
log.Printf("task %d: complete", taskID)
close(done)
}(i, t.Count, t.Interval, t.done[i])
}
return nil
}
// IsAllDone ...
func (t *TaskMgr) IsAllDone() bool {
allDone := true
loop:
for i := 0; i < t.NumRoutines; i++ {
select {
case <-t.done[i]:
log.Printf("task %d is DONE!", i)
default:
allDone = false
break loop
}
}
return allDone
}
func main() {
t := &TaskMgr{
NumRoutines: 4,
Count: 50,
Interval: 100 * time.Millisecond,
}
if err := t.Start(); err != nil {
panic(err)
}
for {
if t.IsAllDone() {
break
}
//time.Sleep(50 * time.Microsecond)
C.usleep(50)
}
}
@enobufs
Copy link
Author

enobufs commented Oct 18, 2019

Deadlock occurred with the above code on an EC2 t2.micro instance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment