Nice! I wasn't aware that the select statement is also for writing to channels, most examples only show reading from channels. Thanks a lot!
On Monday, July 25, 2016 at 5:12:48 AM UTC+2, Alex Bucataru wrote: > > 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.