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.

Reply via email to