Hi Fabian, You could add a signal channel to tell your goroutine to exit. Editing your pseudo code:
data := make(chan byte) done := make(chan struct{}) fd := some file descriptor go func() { buf = make([]byte, 1) for { n, err = syscall.Read(fd, buf) if err != nil { close(data) return } select { case data <- buf[0]: case <- done: return } } } select { case b := <- data: // do something with b case <- timeout: close(done) syscall.Close(fd) } Hope this helps. Cheers, Alex On Sunday, 24 July 2016 18:50:37 UTC-4, fabian....@gmail.com wrote: > > Hi, > > I would like to call syscall.Read() with a timeout. Coming from C, my > first idea was to use syscall.Select(), which should work fine. However, I > came across this answer from 2014 by Ian Lance Taylor to a similar question > (https://groups.google.com/d/msg/golang-nuts/al-6_QFgYaM/UkCqyCQVq_0J): > > The usual approach in Go is to use a simple goroutine that reads from the >> file and writes to a channel. Then you can use the select statement to >> check the channel when appropriate. It's unusual to want to use the poll >> or select system calls since the language gives you other ways to do the >> same thing. > > > I tried it, but I find it harder than it sounds. Here's my pseudo code: > > data := make(chan byte) > fd := some file descriptor > > go func() { > buf = make([]byte, 1) > for { > n, err = syscall.Read(fd, buf) > if err != nil { > close(data) > return > } > data <- buf[0] > } > } > > select { > case b := <- data: > // do something with b > case <- timeout: > syscall.Close(fd) > } > > The idea is obvious: When the timeout is reached, fd is closed, which > interrupts the blocking syscall.Read(), which terminates the goroutine. > > However, there is a race condition: If the timeout is reached immediately > after a successful syscall.Read(), the line 'data <- buf[0]' will block > forever, as no consumer reads data anymore. Adding capacity to the data > channel doesn't help, because theoretically the loop might repeat multiple > times between the timeout is received and fd is actually closed. > > How can I refactor this pseudo code to get rid of the race condition? How > can I implement a syscall.Read() with timeout using a goroutine, channel, > and golang's select statement? > > Thanks for your help > Fabian > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.