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.

Reply via email to