NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

lib/47747: TCP-based RPC client calls no longer terminate when connections break



>Number:         47747
>Category:       lib
>Synopsis:       TCP-based RPC client calls no longer terminate when 
>connections break
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Apr 17 16:05:00 +0000 2013
>Originator:     Thorsten Brehm
>Release:        NetBSD 6.0.1
>Organization:
dSPACE
>Environment:
>Description:
RPC client calls can block indefinitely when using TCP-based RPC connections. 
This happens when the network is interrupted or the remote server processes 
crashes while a RPC call is pending.
 
The problem exists since the following commit:
src/lib/libc/rpc/clnt_vc.c, version 1.18, 2012/03/13 21:13:44
http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/rpc/clnt_vc.c?rev=1.18&content-type=text/x-cvsweb-markup&f=h

Version 1.17 still worked ok.

Diff:
http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/rpc/clnt_vc.c.diff?r1=1.17&r2=1.18&f=h

The problem is caused by the change in line 718, replacing
    return len;
with
    return (int) nread;

A few lines above, there is an error condition assigning
    len = -1;
when detecting a "premature eof" error. Before, this caused "read_vc" to return 
-1 (=len) when the error was detected. Now it returns 0 (=nread) instead. 
Eventually this results in "clnt_call" blocking indefinitely since it keeps 
calling "read_vc" trying to grab all data - rather than aborting with a 
connection error.

Obvious fix: replace
    len = -1;
with
    return (-1);
to properly report the error.

Patch against latest trunk below.
>How-To-Repeat:

>Fix:
diff -wru trunk/clnt_vc.c fix/clnt_vc.c
--- original/lib/libc/rpc/clnt_vc.c     Wed Apr 17 13:46:50 2013 UTC
+++ src/lib/libc/rpc/clnt_vc.c  Mon Mar 11 20:19:29 2013 UTC
@@ -713,8 +713,7 @@
                /* premature eof */
                ct->ct_error.re_errno = ECONNRESET;
                ct->ct_error.re_status = RPC_CANTRECV;
-               len = -1;  /* it's really an error */
-               break;
+               return (-1);  /* it's really an error */
 
        case -1:
                ct->ct_error.re_errno = errno;



Home | Main Index | Thread Index | Old Index