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.

Reply via email to