Ah, cool. So graceful shutdown can be achieved by calling Close() on the 
net.Listener. Nice!

Thank you :)

Tom


On Thursday, August 24, 2017 at 8:20:34 PM UTC+2, Jan Mercl wrote:
>
> net.Listener has a Close method that will make Accept return an error. 
> net.Listener.Accept is not equal to accept(2).
>
> On Thu, Aug 24, 2017, 20:13 Tom Payne <twp...@gmail.com <javascript:>> 
> wrote:
>
>> Thanks. Looking at the man page for Linux's accept(2) 
>> http://man7.org/linux/man-pages/man2/accept.2.html it seems that 
>> l.Accept is unlikely to ever return an error.
>>
>> accept(2) returns an error if either the connection is incorrectly set up 
>> somehow, or if a system call is interrupted by a signal, or if the process 
>> or system runs out of resources (either file handles or memory).
>>
>> Setup problems should occur immediately (before any client connection is 
>> actually accepted) so there is no race there. It looks to me that EINTR is 
>> *not* handled by Go's runtime so real world (not prototypical) server code 
>> needs to handle EINTR, but there is no race condition in the code (in the 
>> case of a signal, the function will terminate without leaking resources). 
>> In the case of resource exhaustion it's hard to implement sane behaviour in 
>> any case.
>>
>> Thanks again for the discussion - I'm learning a lot here. Is there 
>> anything above that is not correct?
>>
>> Cheers,
>> Tom
>>
>>
>> On Thursday, August 24, 2017 at 7:56:22 PM UTC+2, Jan Mercl wrote:
>>
>>> The wg.Wait will be executed after l.Accept returns an error. It's 
>>> purpose is to wait for the completions of all handlers invoked in the go 
>>> statement that did not finished already.
>>>
>>> On Thu, Aug 24, 2017, 19:49 Tom Payne <twp...@gmail.com> wrote:
>>>
>>>> Awesome, thanks Jan for the fast and clear response.
>>>>
>>>> In fact, the for {} is an infinite loop so wg.Wait() will never be 
>>>> reached and serve() will never terminate. Correct?
>>>>
>>>> I guess I over-read how much this prototypical code was representative 
>>>> of a real server loop. Sorry Dave!
>>>>
>>>> Tom
>>>>
>>>> On Thursday, August 24, 2017 at 7:41:59 PM UTC+2, Jan Mercl wrote:
>>>>
>>>>> No, wg.Add cannot "switch" to wg.Wait, they're both in the samr 
>>>>> goroutine, the go statement will be always the next one to execute after 
>>>>> wg.Add within serve().
>>>>>
>>>>> On Thu, Aug 24, 2017, 19:29 Tom Payne <twp...@gmail.com> wrote:
>>>>>
>>>> I'm not singling out Dave Cheney here, I'd just like to check my 
>>>>>> understanding of Go's resource handling and concurrency.
>>>>>>
>>>>>> In this blog post a "prototypical network server" is presented:
>>>>>>
>>>>>>    https://dave.cheney.net/2017/08/20/context-isnt-for-cancellation
>>>>>>
>>>>>> Code:
>>>>>>
>>>>>> func serve(l net.Listener) error {
>>>>>>         var wg sync.WaitGroup
>>>>>>         var conn net.Conn
>>>>>>         var err error
>>>>>>         for {
>>>>>>                 conn, err = l.Accept()
>>>>>>                 if err != nil {
>>>>>>                         break
>>>>>>                 }
>>>>>>                 wg.Add(1)
>>>>>>                 go func(c net.Conn) {
>>>>>>                         defer wg.Done()
>>>>>>                         handle(c)
>>>>>>                 }(conn)
>>>>>>         }
>>>>>>         wg.Wait()
>>>>>>         return err
>>>>>> }
>>>>>>
>>>>>> My understanding is that this contains a race condition. 
>>>>>> Specifically, a goroutine switch can occur at the entry to wg.Add(1), 
>>>>>> switching to wg.Wait() in the main goroutine. At this point, a 
>>>>>> connection 
>>>>>> has been accepted, but the WaitGroup counter has not been incremented, 
>>>>>> so 
>>>>>> the serve function will terminate while silently dropping a network 
>>>>>> connection (the connection will be accepted, but never handled, so will 
>>>>>> probably eventually time out on the client side and leak a file 
>>>>>> descriptor 
>>>>>> on the server side).
>>>>>>
>>>>>> Is this understanding correct? Furthermore, I suspect that it's 
>>>>>> impossible to implement race-free graceful termination using only 
>>>>>> sync.WaitGroups. Is it actually possible to do so?
>>>>>>
>>>>>> Thanks for any correction, and apologies to Dave for picking on his 
>>>>>> code.
>>>>>>
>>>>>> Cheers,
>>>>>> Tom
>>>>>>
>>>>>> -- 
>>>>>> 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...@googlegroups.com.
>>>>>
>>>>>
>>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>>
>>>>> -- 
>>>>>
>>>>> -j
>>>>>
>>>> -- 
>>>> 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...@googlegroups.com.
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>> -- 
>>>
>>> -j
>>>
>> -- 
>> 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...@googlegroups.com <javascript:>.
>> For more options, visit https://groups.google.com/d/optout.
>>
> -- 
>
> -j
>

-- 
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