Discussion:
"use of closed network connection" error from TCPConn.Read
James Bardin
2013-01-19 00:51:08 UTC
Permalink
Please ignore my previous post (pending moderation), Read() on a TCPConn
does not return (0, nil).

Since I figure I have to deal with the "use of closed network connection"
in order to close a connection that's in a Read() call (unless I poll for a
closing channel in between setting SetReadDeadline).This is basically the
function I have to filter out this error:

func checkNetOpError(err error) error {
if err != nil {
netOpError, ok := err.(*net.OpError)
if ok && netOpError.Err.Error() == "use of closed network connection" {
return nil
}
}
return err
}


This seems awkward though; is this the best way to handle this?


--
Dave Cheney
2013-01-19 06:58:42 UTC
Permalink
To quote Mr Pike, can you please describe your problem, not your solution.
Please ignore my previous post (pending moderation), Read() on a TCPConn does not return (0, nil).
func checkNetOpError(err error) error {
if err != nil {
netOpError, ok := err.(*net.OpError)
if ok && netOpError.Err.Error() == "use of closed network connection" {
return nil
}
}
return err
}
This seems awkward though; is this the best way to handle this?
--
--
James Bardin
2013-01-19 19:17:19 UTC
Permalink
Post by Dave Cheney
To quote Mr Pike, can you please describe your problem, not your solution.
Yeah, I didn't really give enough context.
This part of the code is a simple proxy, copying the data between two tcp
connections. If either connection closes, I need to close the other half of
the pair. The problem is that the other connection will almost always be in
a Read() call, and will return a net.OpError with "use of closed network
connection". Though I won't need to take action on other errors, I'll need
to log them, as they'll be exceptional cases.

I could of course drop down to a lower level, do the copy myself,
SetReadDeadline on the sockets and poll for a close signal, but that's a
lot of work when to goroutines with io.Copy() works so well.

I thought it would be easier to just handle the specific error, but being
relatively new to go, figuring out how to extract and match the string was
a little bit of a challenge. Is this the best way to differentiate the
error, or is there another way to structure the problems that I'm not
thinking of?

Thanks!
Post by Dave Cheney
Please ignore my previous post (pending moderation), Read() on a TCPConn
does not return (0, nil).
Since I figure I have to deal with the "use of closed network connection"
in order to close a connection that's in a Read() call (unless I poll for a
closing channel in between setting SetReadDeadline).This is basically the
func checkNetOpError(err error) error {
if err != nil {
netOpError, ok := err.(*net.OpError)
if ok && netOpError.Err.Error() == "use of closed network connection" {
return nil
}
}
return err
}
This seems awkward though; is this the best way to handle this?
--
--
Dave Cheney
2013-01-20 01:09:39 UTC
Permalink
Hi,

Here are a few suggestions.

Try +tip, this smells like a windows weirdness that should be expunged in the development version

If you are coping data in both directions then try Shutdown rather than Close, that it what it is there for. You may need to also use a wait group to synchronise the action of the io.Copy in the goroutine and the io.Copy in the main goroutine.
Post by James Bardin
Post by Dave Cheney
To quote Mr Pike, can you please describe your problem, not your solution.
Yeah, I didn't really give enough context.
This part of the code is a simple proxy, copying the data between two tcp connections. If either connection closes, I need to close the other half of the pair. The problem is that the other connection will almost always be in a Read() call, and will return a net.OpError with "use of closed network connection". Though I won't need to take action on other errors, I'll need to log them, as they'll be exceptional cases.
I could of course drop down to a lower level, do the copy myself, SetReadDeadline on the sockets and poll for a close signal, but that's a lot of work when to goroutines with io.Copy() works so well.
I thought it would be easier to just handle the specific error, but being relatively new to go, figuring out how to extract and match the string was a little bit of a challenge. Is this the best way to differentiate the error, or is there another way to structure the problems that I'm not thinking of?
Thanks!
Post by Dave Cheney
Please ignore my previous post (pending moderation), Read() on a TCPConn does not return (0, nil).
func checkNetOpError(err error) error {
if err != nil {
netOpError, ok := err.(*net.OpError)
if ok && netOpError.Err.Error() == "use of closed network connection" {
return nil
}
}
return err
}
This seems awkward though; is this the best way to handle this?
--
--
--
James Bardin
2013-01-20 02:42:40 UTC
Permalink
Post by Dave Cheney
Try +tip, this smells like a windows weirdness that should be expunged in
the development version
Yeah, tip has the same behavior.
Post by Dave Cheney
If you are coping data in both directions then try Shutdown rather than
Close, that it what it is there for. You may need to also use a wait group
to synchronise the action of the io.Copy in the goroutine and the io.Copy
in the main goroutine.
I'm not following you here. A TCPConn doesn't have a Shutdown method, nor
is there any reference to once in the net package.

I think have the synchronization working for what I need; if the caller
gets signalled that either connection closed, it then closes the other.
That second connection will almost always be in a blocking Read call.

Though, not using io.Copy, I think this is minimal example if the problem:

//
func read(conn *net.TCPConn) {
buff := make([]byte, 1024)
_, err := conn.Read(buff)
if err != nil {
fmt.Println(err)
}
}

func main() {
remoteAddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:8080")
conn, _ := net.DialTCP("tcp", nil, remoteAddr)
go read(conn)
time.Sleep(1 * time.Second)
conn.Close()
}
//


Assuming you have a server on 8080, this will return
"read tcp 127.0.0.1:8080: use of closed network connection"


Thanks.

--
Dave Cheney
2013-01-20 02:44:59 UTC
Permalink
Sorry about that, I was mistaken about the name.

http://golang.org/pkg/net/#TCPConn.CloseRead
Post by James Bardin
Post by Dave Cheney
Try +tip, this smells like a windows weirdness that should be expunged in
the development version
Yeah, tip has the same behavior.
Post by Dave Cheney
If you are coping data in both directions then try Shutdown rather than
Close, that it what it is there for. You may need to also use a wait group
to synchronise the action of the io.Copy in the goroutine and the io.Copy
in the main goroutine.
I'm not following you here. A TCPConn doesn't have a Shutdown method, nor
is there any reference to once in the net package.
I think have the synchronization working for what I need; if the caller
gets signalled that either connection closed, it then closes the other.
That second connection will almost always be in a blocking Read call.
//
func read(conn *net.TCPConn) {
buff := make([]byte, 1024)
_, err := conn.Read(buff)
if err != nil {
fmt.Println(err)
}
}
func main() {
remoteAddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:8080")
conn, _ := net.DialTCP("tcp", nil, remoteAddr)
go read(conn)
time.Sleep(1 * time.Second)
conn.Close()
}
//
Assuming you have a server on 8080, this will return
"read tcp 127.0.0.1:8080: use of closed network connection"
Thanks.
--
--
James Bardin
2013-01-20 03:00:31 UTC
Permalink
Post by Dave Cheney
Sorry about that, I was mistaken about the name.
http://golang.org/pkg/net/#TCPConn.CloseRead
Ah, now that looks promising, and from my quick tests, it's exactly what I
need. I passed over trying this for some reason, probably because there
wasn't much documentation.

Thanks again!

--

Loading...