On Tuesday, 12 September 2017 15:23:56 UTC+10, Shivaram Lingamneni wrote:
>
> So this proves it: "happens-after Listener.Close()" is not a sufficient 
> condition for being able to rebind the address. If another goroutine is in 
> a Listener.Accept() call, the new bind must happen-after the return of both 
> the Listener.Close() and the Listener.Accept() calls.
>

Please see this code https://play.golang.org/p/j7ZxGbf4py
 

>
> So the question is: are there any other conditions that can prevent 
> Listener.Close() from resulting in close(2)? Is code that waits for the 
> completion of both Close() and Accept() correct code?
>

Not for network sockets.
 

>
> I don't understand the polling layer of the runtime to say whether it 
> would be feasible for `Accept()` not to hold a reference during 
> `WaitRead()` --- but it seems like that would be preferable.
>

Once Accept has returned, the readLock is returned. Accept returns when it 
receives a connection, or its underlying socket is closed via l.Close()
 

>
> On Tuesday, September 12, 2017 at 12:39:11 AM UTC-4, Dave Cheney wrote:
>>
>> Yup, and when l.Close is called, Accept returns, releasing the readLock.
>>
>>
>> https://github.com/golang/go/blob/2d69e9e259ec0f5d5fbeb3498fbd9fed135fe869/src/internal/poll/fd_unix.go#L321
>>
>> On Tuesday, 12 September 2017 14:30:54 UTC+10, Shivaram Lingamneni wrote:
>>>
>>>
>>>
>>> On Tuesday, September 12, 2017 at 12:13:15 AM UTC-4, Dave Cheney wrote:
>>>>
>>>>
>>>>
>>>> On Tuesday, 12 September 2017 13:40:04 UTC+10, Shivaram Lingamneni 
>>>> wrote:
>>>>>
>>>>> On Monday, September 11, 2017 at 11:17:01 PM UTC-4, Dave Cheney wrote:
>>>>>>
>>>>>> The already in use is probably coming from the TCP stack which waits 
>>>>>> a certain time before allowing the address to be reused. However I 
>>>>>> thought 
>>>>>> that the net package already used SO_REUSEADDR to avoid the delay in 
>>>>>> close 
>>>>>> to reopen.
>>>>>>
>>>>>>
>>>>>>> The question I'm really asking is not so much how to write code that 
>>>>>>> works in practice (or, rather, appears to do so), but how to be certain 
>>>>>>> (on 
>>>>>>> the basis of the specification and API documentation) that the code is 
>>>>>>> correct.
>>>>>>>
>>>>>>
>>>>>> As written the code is correct. Once the listener is closed, you can 
>>>>>> reopen it, modulo TCP stack vagaries. 
>>>>>>
>>>>>
>>>>> The net package is indeed setting SO_REUSEADDR, which allows re-bind 
>>>>> on the address immediately after close(2). The problem is that close(2) 
>>>>> is 
>>>>> not guaranteed to occur as a result of Listener.Close(), because of 
>>>>> reference counting of file descriptors. This is not an issue with the TCP 
>>>>> stack; the runtime is simply failing to issue the required system call.
>>>>>
>>>>
>>>> I've had a look through the code for the TCPListener and I cannot see 
>>>> where the reference count is being bumped by accept. As far as I 
>>>> understand 
>>>> the *netFD returned from Accept is unassociated with the *netFD that is 
>>>> bound to a listening socket. 
>>>>
>>>
>>> On the one hand, I am more confident in the claim that "close(2) is not 
>>> guaranteed to occur as a result of Listener.Close()" than I am in the 
>>> specific explanation of `Accept()` holding a reference. On the other hand, 
>>> I think I found the relevant line of code:
>>>
>>>
>>> https://github.com/golang/go/blob/2d69e9e259ec0f5d5fbeb3498fbd9fed135fe869/src/internal/poll/fd_unix.go#L318
>>>  
>>>
>>> If I'm reading this correctly, this layer of Accept() acquires a 
>>> readLock() on the file, which includes a reference acquire:
>>>
>>>
>>> https://github.com/golang/go/blob/2d69e9e259ec0f5d5fbeb3498fbd9fed135fe869/src/internal/poll/fd_mutex.go#L216
>>>
>>> and then continues holding this reference when it "blocks" on 
>>> `fd.pd.WaitRead`.
>>>
>>

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