PR/31264: Mark Davies: rup not interruptable

The cause of this is that in the re-entrant case we block all signals until
we timeout. Convert this to use pollts and then grab the pending signals
and sigsuspend them.
XXX: We should really convert this to use kqueue, like FreeBSD did.
This commit is contained in:
christos 2005-09-09 15:40:49 +00:00
parent 03d7777e5c
commit fa92811fc7
1 changed files with 21 additions and 33 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: clnt_dg.c,v 1.15 2005/06/09 22:13:17 yamt Exp $ */
/* $NetBSD: clnt_dg.c,v 1.16 2005/09/09 15:40:49 christos Exp $ */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
@ -39,7 +39,7 @@
#if 0
static char sccsid[] = "@(#)clnt_dg.c 1.19 89/03/16 Copyr 1988 Sun Micro";
#else
__RCSID("$NetBSD: clnt_dg.c,v 1.15 2005/06/09 22:13:17 yamt Exp $");
__RCSID("$NetBSD: clnt_dg.c,v 1.16 2005/09/09 15:40:49 christos Exp $");
#endif
#endif
@ -80,7 +80,6 @@ static bool_t clnt_dg_freeres __P((CLIENT *, xdrproc_t, caddr_t));
static void clnt_dg_abort __P((CLIENT *));
static bool_t clnt_dg_control __P((CLIENT *, u_int, char *));
static void clnt_dg_destroy __P((CLIENT *));
static int __rpc_timeval_to_msec __P((struct timeval *));
@ -323,10 +322,13 @@ clnt_dg_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
struct timeval startime, curtime;
int firsttimeout = 1;
#ifdef _REENTRANT
sigset_t mask;
sigset_t mask, maskp = &mask;
#else
sigset_t maskp = NULL;
#endif
sigset_t newmask;
ssize_t recvlen = 0;
struct timespec ts;
_DIAGASSERT(cl != NULL);
@ -392,8 +394,8 @@ send_again:
for (;;) {
switch (poll(&cu->pfdp, 1,
__rpc_timeval_to_msec(&retransmit_time))) {
TIMEVAL_TO_TIMESPEC(&retransmit_time, &ts);
switch (pollts(&cu->pfdp, 1, &ts, maskp)) {
case 0:
time_waited.tv_sec += retransmit_time.tv_sec;
time_waited.tv_usec += retransmit_time.tv_usec;
@ -468,6 +470,18 @@ send_again:
release_fd_lock(cu->cu_fd, mask);
return (cu->cu_error.re_status = RPC_TIMEDOUT);
}
#ifdef _REENTRANT
if (errno == EINTR) {
sigset_t rmask;
if (sigpending(&rmask) == -1) {
cu->cu_error.re_errno = errno;
release_fd_lock(cu->cu_fd, mask);
return cu->cu_error.re_status =
RPC_SYSTEMERROR;
}
(void)sigsuspend(&rmask);
}
#endif
errno = 0; /* reset it */
continue;
};
@ -476,7 +490,7 @@ send_again:
cu->cu_error.re_status = RPC_CANTRECV;
/*
* Note: we're faking errno here because we
* previously would have expected poll() to
* previously would have expected pollts() to
* return -1 with errno EBADF. Poll(BA_OS)
* returns 0 and sets the POLLNVAL revents flag
* instead.
@ -832,29 +846,3 @@ time_not_ok(t)
return (t->tv_sec < -1 || t->tv_sec > 100000000 ||
t->tv_usec < -1 || t->tv_usec > 1000000);
}
/*
* Convert from timevals (used by select) to milliseconds (used by poll).
*/
static int
__rpc_timeval_to_msec(t)
struct timeval *t;
{
int t1, tmp;
_DIAGASSERT(t != NULL);
/*
* We're really returning t->tv_sec * 1000 + (t->tv_usec / 1000)
* but try to do so efficiently. Note: 1000 = 1024 - 16 - 8.
*/
tmp = (int)t->tv_sec << 3;
t1 = -tmp;
t1 += t1 << 1;
t1 += tmp << 7;
if (t->tv_usec)
t1 += (int)(t->tv_usec / 1000);
return (t1);
}