Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net: can {Conn,PacketConn}.Close block? #18187

dsnet opened this issue Dec 3, 2016 · 7 comments

net: can {Conn,PacketConn}.Close block? #18187

dsnet opened this issue Dec 3, 2016 · 7 comments


Copy link

@dsnet dsnet commented Dec 3, 2016

The documentation for net.Conn.Close is:

Close closes the connection. Any blocked Read or Write operations will be unblocked and return errors.

However, it does not mention anything about whether Close itself can block.

Some net.Conn implementations have an implicit write buffer. Thus, when Close is called, it still needs to flush the buffer before returning. This means that Close is effectively an operation that involves IO. Since it involves IO, this means that Close may have to wait until the recipient acknowledges the incoming data (which could potentially be forever if the receiver's read buffer is full).

If we extend the documentation for net.Conn.Close, would the following be reasonable?

Close closes the connection. Any blocked Read or Write operations will be unblocked and return errors. Close itself may block while it is flushing any internal write buffers, but must return an error and terminate the connection when a previously set write deadline is exceeded.

\cc @bradfitz @mikioh

@dsnet dsnet added this to the Go1.8 milestone Dec 3, 2016
Copy link
Member Author

@dsnet dsnet commented Dec 3, 2016

For reasons that I don't understand, I'm not able to get TCPConn.Close to block even when I write as much data on one endpoint while nothing is reading on the other endpoint.

In other implementations I'm looking at, it is impossible to get Close to be non-blocking since the underlying layers provide no control over flushing and have implicit write buffers built into them.

@mikioh mikioh changed the title net: can Conn.Close block? net: can {Conn,PacketConn}.Close block? Dec 4, 2016
Copy link

@mikioh mikioh commented Dec 4, 2016

#10527 is for Listener.Close.

Copy link

@bradfitz bradfitz commented Dec 4, 2016

Yes, we've had to make changes to the net/http package in the past due to net.Conn implementations blocking on Close. If it's an interface, anything can happen. It's fine to document that it may block, if it's not overly wordy.

@bradfitz bradfitz added NeedsFix and removed NeedsDecision labels Dec 4, 2016
@bradfitz bradfitz modified the milestones: Go1.9Maybe, Go1.8, Go1.8Maybe Dec 5, 2016
@bradfitz bradfitz modified the milestones: Go1.9, Go1.8Maybe Dec 15, 2016
@bradfitz bradfitz modified the milestones: Go1.10, Go1.9 Jun 26, 2017
@dsnet dsnet modified the milestones: Go1.10, Unplanned Nov 10, 2017
@dsnet dsnet removed their assignment Dec 6, 2017
Copy link

@dunjut dunjut commented Mar 13, 2019

Is it possible or not that a TCPConn.Close() may block?

Copy link

@arkaml arkaml commented Mar 29, 2019


I have a "high concurrency" client on a payment processing solution under production which when it detects the connection might be dead (multiple concurrent errors on non blocking read() or write() calls) it enters a reconnect loop to different secondary backup servers until it gets able to keep processing transactions.

A couple of days ago the single threaded component handling de TCP socket I/O hanged out, watching the source code for hours i couldn't find a single blocking condition, suddenly i realized, might be Close() blocking?

Why i perform the Close call? because the underlying protocol (old credit cards processing protocol implementation) would send back responses on any opened detected socket, no matter in which socket it received the request.. so if i don't perform the correct TCP connection closure before establishing a new TCP connection i might get into an scenario were the responses for the requests sent through the new established socket might start getting back in the original connection once the networking issue gets solved.

So, the question made by @dunjut is really critical in my scenario. Is Close() candidate to block? I was really not expecting this condition to happen :(

Copy link

@JFR-Adroll JFR-Adroll commented Apr 4, 2019

You can have a blocking conn.Close by doing something like:

reader := bufio.NewReader(conn)
go io.ReadFull(reader, buf)
Copy link

@Windsooon Windsooon commented May 23, 2019

@dsnet Did you create a PR for it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
7 participants
You can’t perform that action at this time.