gob decode from socket with read timeout

373 views
Skip to first unread message

Albert Strasheim

unread,
Jan 19, 2011, 2:09:47 AM1/19/11
to golang-nuts
Hello all

We have a goroutine reading from a socket.

We would like to be able to shutdown the goroutine cleanly.

When just doing a normal read, the best idea I've come up with so far
is to set a read timeout on the socket so that the read will return
every second or so, so that we can check a flag or a channel to see
whether the goroutine should exit.

However, I'm not quite sure how to proceed if we want to read gob-
encoded objects from the socket.

gob.NewDecoder takes an io.Reader, which is fine. But as far as I can
see from the code, it's not going to do the right thing with the error
that is returned when a read timeout happens.

Maybe it's not gob's responsibility to deal with read timeouts, but is
there some way to feed bytes into gob if I do the reading into another
buffer first (and dealing with read timeouts as part of this)?

Another consideration: if we need to communicate with non-Go programs
later, it would be useful to be able to replace gob with goprotobuf.

Any suggestions?

Thanks!

Regards

Albert

Rob 'Commander' Pike

unread,
Jan 19, 2011, 3:07:33 AM1/19/11
to Albert Strasheim, golang-nuts
You don't define what you mean by "shutdown the goroutine cleanly". If a socket shuts down, any read will get EOF and all should work. If you don't want any error, EOF or otherwise, to generate a problem, interpose a goroutine that feeds data through (Reader to Reader), turning any error into EOFs. If you want a general condition to shut down the goroutine, select either a shutdown channel or a channel of new data to feed. When the shutdown is triggered, deliver EOF on the output channel.

-rob

Albert Strasheim

unread,
Jan 19, 2011, 3:35:20 AM1/19/11
to Rob 'Commander' Pike, golang-nuts
Hello

Thanks for the comments. Let me explain a bit more about what we're
trying to do.

A server accepts client connections on a listener.

For each connection, it spawns a "handler" goroutine to deal with the
client session.

In turn, the handler spawns a "reader" and a "writer".

Then the handler sits in a loop, reading from its channel.

Messages to this handler channel can come from two places: another
goroutine in the server, or the "reader".

The reader is blocked in Read on the socket. If it reads something, it
sends a message to the handler.

If the handler wants to write to the socket, it sends a message to the
writer. Another design could have the handler write to the socket
directly. Here be trade-offs.

If the client closes the socket, the reader gets an EOF, sends a
message to the handler and shuts down.

Now the question is what happens when the server decides that one of
the handlers should terminate.

It sends a message to the handler on its channel. The handler now has
to shut down the reader.

How does it do that? Can it simply close the socket that the reader is
doing a blocking Read on? If it can, then having a reader that uses a
gob Decoder will work fine.

If not, the reader has to set a read timeout and check for a shutdown
request periodically.

Thanks.

Regards

Albert

roger peppe

unread,
Jan 19, 2011, 4:30:22 AM1/19/11
to Albert Strasheim, Rob 'Commander' Pike, golang-nuts
On 19 January 2011 08:35, Albert Strasheim <ful...@gmail.com> wrote:
> How does it do that? Can it simply close the socket that the reader is
> doing a blocking Read on? If it can, then having a reader that uses a
> gob Decoder will work fine.

by experiment (on macos x) this works fine.
the documentation should probably say it's ok to
do this though, as the convention is that it's
not allowable to call methods concurrently on a value.

interestingly, closing a tcp Listener does not cause
an Accept to terminate - i guess that means there's
no way to listen on a port and then stop listening on that port.

Albert Strasheim

unread,
Jan 19, 2011, 4:33:53 AM1/19/11
to roger peppe, Rob 'Commander' Pike, golang-nuts
Hello

On Wed, Jan 19, 2011 at 11:30 AM, roger peppe <rogp...@gmail.com> wrote:
> On 19 January 2011 08:35, Albert Strasheim <ful...@gmail.com> wrote:
>> How does it do that? Can it simply close the socket that the reader is
>> doing a blocking Read on? If it can, then having a reader that uses a
>> gob Decoder will work fine.
> by experiment (on macos x) this works fine.
> the documentation should probably say it's ok to
> do this though, as the convention is that it's
> not allowable to call methods concurrently on a value.

Thanks for the feedback. I'll give it a try.

With regards to Accept, I think you're seeing this issue:

http://code.google.com/p/go/issues/detail?id=1059

Another related issue which can cause problems with this approach is:

http://code.google.com/p/go/issues/detail?id=1058

Regards

Albert

Russ Cox

unread,
Jan 19, 2011, 9:46:15 AM1/19/11
to roger peppe, Albert Strasheim, Rob 'Commander' Pike, golang-nuts
> by experiment (on macos x) this works fine.
> the documentation should probably say it's ok to
> do this though, as the convention is that it's
> not allowable to call methods concurrently on a value.

yes. package net works hard to make sure
Close cancels any pending Read and Write calls.

> interestingly, closing a tcp Listener does not cause
> an Accept to terminate - i guess that means there's
> no way to listen on a port and then stop listening on that port.

are you seeing this at tip? i thought we fixed that
in late december.

russ

roger peppe

unread,
Jan 19, 2011, 9:58:25 AM1/19/11
to r...@golang.org, Albert Strasheim, Rob 'Commander' Pike, golang-nuts
On 19 January 2011 14:46, Russ Cox <r...@golang.org> wrote:
>> interestingly, closing a tcp Listener does not cause
>> an Accept to terminate - i guess that means there's
>> no way to listen on a port and then stop listening on that port.
>
> are you seeing this at tip?  i thought we fixed that
> in late december.

yes i am.

Reply all
Reply to author
Forward
0 new messages