diff --git a/ChangeLog b/ChangeLog index 1a2e4da..3c9427f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2012-11-28 Jeff Law + Martin Osvald + + * sunrpc/rpc/svc.h (__svc_accept_failed): New prototype. + * sunrpc/svc.c: Include time.h. + (__svc_accept_failed): New function. + * sunrpc/svc_tcp.c (rendezvous_request): If the accept fails for + any reason other than EINTR, call __svc_accept_failed. + * sunrpc/svc_udp.c (svcudp_recv): Similarly. + * sunrpc/svc_unix.c (rendezvous_request): Similarly. + 2012-11-27 Siddhesh Poyarekar [BZ #11741] diff --git a/sunrpc/rpc/svc.h b/sunrpc/rpc/svc.h index 54d1ac1..b324b74 100644 --- a/sunrpc/rpc/svc.h +++ b/sunrpc/rpc/svc.h @@ -316,4 +316,5 @@ extern SVCXPRT *svcunix_create (int __sock, u_int __sendsize, u_int __recvsize, __END_DECLS +extern void __svc_accept_failed (void) attribute_hidden; #endif /* rpc/svc.h */ diff --git a/sunrpc/svc.c b/sunrpc/svc.c index 103770a..e48be67 100644 --- a/sunrpc/svc.c +++ b/sunrpc/svc.c @@ -41,6 +41,7 @@ #include #include #include +#include #ifdef _RPC_THREAD_SAFE_ #define xports RPC_THREAD_VARIABLE(svc_xports_s) @@ -544,6 +545,21 @@ svc_getreq_common (const int fd) } libc_hidden_nolink_sunrpc (svc_getreq_common, GLIBC_2_2) +/* If there are no file descriptors available, then accept will fail. + We want to delay here so the connection request can be dequeued; + otherwise we can bounce between polling and accepting, never giving the + request a chance to dequeue and eating an enormous amount of cpu time + in svc_run if we're polling on many file descriptors. */ +void +__svc_accept_failed (void) +{ + if (errno == EMFILE) + { + struct timespec ts = { .tv_sec = 0, .tv_nsec = 50000000 }; + __nanosleep (&ts, NULL); + } +} + #ifdef _RPC_THREAD_SAFE_ void diff --git a/sunrpc/svc_tcp.c b/sunrpc/svc_tcp.c index eb61549..93f2ae2 100644 --- a/sunrpc/svc_tcp.c +++ b/sunrpc/svc_tcp.c @@ -247,6 +247,7 @@ again: { if (errno == EINTR) goto again; + __svc_accept_failed (); return FALSE; } /* diff --git a/sunrpc/svc_udp.c b/sunrpc/svc_udp.c index 6c4d75a..3bd718b 100644 --- a/sunrpc/svc_udp.c +++ b/sunrpc/svc_udp.c @@ -277,8 +277,12 @@ again: (int) su->su_iosz, 0, (struct sockaddr *) &(xprt->xp_raddr), &len); xprt->xp_addrlen = len; - if (rlen == -1 && errno == EINTR) - goto again; + if (rlen == -1) + { + if (errno == EINTR) + goto again; + __svc_accept_failed (); + } if (rlen < 16) /* < 4 32-bit ints? */ return FALSE; xdrs->x_op = XDR_DECODE; diff --git a/sunrpc/svc_unix.c b/sunrpc/svc_unix.c index 94507b2..5de09c6 100644 --- a/sunrpc/svc_unix.c +++ b/sunrpc/svc_unix.c @@ -244,6 +244,7 @@ again: { if (errno == EINTR) goto again; + __svc_accept_failed (); return FALSE; } /*