How to handle rpc EOF error?

6,291 views
Skip to first unread message

Mad Go

unread,
Sep 29, 2010, 10:55:35 PM9/29/10
to golang-nuts
Hi,

When rpc server crash, the client would get "rpc: client protocol
error: unexpected EOF", but after that, the client just get "EOF"
error even the server side is start again, how do I handle it? I tried
to auto dial server again but nothing changed. I would really
appreciate if anyone can give a short code, thanks!

Andrew Gerrand

unread,
Sep 29, 2010, 11:58:16 PM9/29/10
to Mad Go, golang-nuts
How are you redialing? Do you create a new Client when you redial?

Mad Go

unread,
Sep 30, 2010, 1:26:25 AM9/30/10
to golang-nuts
I define a func Dial(), and try to re-call it after get EOF error, is
it useless? You mean I shoud create a new conn at client side? or
server side? Sorry that I'm a newbie of rpc.

func Dial() {
Dial:
if menu_food_client, err = rpc.Dial("unix", "/var/run/
menu_food.sock"); err != nil {
LogError("dialing error:", err)
time.Sleep(3e9)
goto Dial
}
}


On Sep 30, 11:58 am, Andrew Gerrand <a...@golang.org> wrote:
> How are you redialing? Do you create a new Client when you redial?
>

Andrew Gerrand

unread,
Sep 30, 2010, 1:32:46 AM9/30/10
to Mad Go, golang-nuts
On 30 September 2010 15:26, Mad Go <madd...@gmail.com> wrote:
> I define a func Dial(), and try to re-call it after get EOF error, is
> it useless? You mean I shoud create a new conn at client side? or
> server side? Sorry that I'm a newbie of rpc.
>
> func Dial() {
>        Dial:
>        if menu_food_client, err = rpc.Dial("unix", "/var/run/
> menu_food.sock"); err != nil {
>                LogError("dialing error:", err)
>                time.Sleep(3e9)
>                goto Dial
>        }
> }

This will only redial if the initial Dial fails. What happens if the
original Dial is successful, but the connection goes away (ie, the
server dies)? In that case, you need to Dial again to re-establish the
connection (make sure you Close it first).

Andrew

Mad Go

unread,
Sep 30, 2010, 5:40:49 AM9/30/10
to golang-nuts
Hi Andrew,

Thanks for your help, I know the reason, I changed the func:

func Dial() {
DialMenu_food:
if conn, err = net.Dial("unix", "", "/var/run/menu_food.sock");
err != nil {
LogError("dialing error:", err)
time.Sleep(3e9)
goto DialMenu_food
}
menu_food_client = rpc.NewClient(menu_food_conn)
}

And call conn.Close();Dial(); after EOF error, then everything is
ok, thanks.

Another question, should I use such struct to distinguish whether the
error is from rpc connection or from my server side code(so that I can
decide to re-dial or not):
type RpcReply struct {
Err string
SomethingRealNeed string/int/struct...
}
If I use such struct for reply data, I must define reply data type for
every remote func.

Or just use the error returned by rpc.Go/rpc.Call? Now I use
regexp.Compile("EOF") to pick the rpc connection error, but I'm not
sure it could handle all the situations, pls give me some advice,
thanks.

On Sep 30, 1:32 pm, Andrew Gerrand <a...@golang.org> wrote:

Andrew Gerrand

unread,
Oct 1, 2010, 12:56:14 AM10/1/10
to Mad Go, golang-nuts
On 30 September 2010 19:40, Mad Go <madd...@gmail.com> wrote:
> Another question, should I use such struct to distinguish whether the
> error is from rpc connection or from my server side code(so that I can
> decide to re-dial or not):
> type RpcReply struct {
>    Err string
>    SomethingRealNeed string/int/struct...
> }
> If I use such struct for reply data, I must define reply data type for
> every remote func.
>
> Or just use the error returned by rpc.Go/rpc.Call? Now I use
> regexp.Compile("EOF") to pick the rpc connection error, but I'm not
> sure it could handle all the situations, pls give me some advice,
> thanks.

os.Error is an interface, so you can make your own types that
implement that interface. There's even a helper function to do it for
you:

var (
InvalidRequestError = os.NewError("invalid request")
InternalError = os.NewError("internal server error")
)

Then you can test whether the error value returned by Call is one of
your application's errors. A switch is helpful here:

err := c.Call("Server.Method", &args, &result)
if err != nil {
switch err {
case InvalidRequestError:
// etc
case InternalError:
// etc
default:
// some other error
}

Andrew

Mad Go

unread,
Oct 1, 2010, 11:27:05 AM10/1/10
to golang-nuts
Got it, thanks!

On 10月1日, 下午12时56分, Andrew Gerrand <a...@golang.org> wrote:
Reply all
Reply to author
Forward
0 new messages