Index: rpc/clnt_rc.c =================================================================== --- rpc/clnt_rc.c +++ rpc/clnt_rc.c @@ -174,10 +174,26 @@ newclient = clnt_dg_create(so, (struct sockaddr *) &rc->rc_addr, rc->rc_prog, rc->rc_vers, rc->rc_sendsz, rc->rc_recvsz); - else + else { + /* + * I do not believe a timeout of less than 1sec would make + * sense here since short delays can occur when a server is + * temporarily overloaded. + */ + if (rc->rc_timeout.tv_sec > 0 && rc->rc_timeout.tv_usec >= 0) { + error = so_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO, + &rc->rc_timeout, sizeof(struct timeval)); + if (error != 0) { + stat = rpc_createerr.cf_stat = RPC_CANTSEND; + rpc_createerr.cf_error.re_errno = error; + td->td_ucred = oldcred; + goto out; + } + } newclient = clnt_vc_create(so, (struct sockaddr *) &rc->rc_addr, rc->rc_prog, rc->rc_vers, rc->rc_sendsz, rc->rc_recvsz, rc->rc_intr); + } td->td_ucred = oldcred; if (!newclient) { Index: rpc/clnt_vc.c =================================================================== --- rpc/clnt_vc.c +++ rpc/clnt_vc.c @@ -142,6 +142,8 @@ XDR xdrs; int error, interrupted, one = 1, sleep_flag; struct sockopt sopt; + struct timeval tv; + int timo; if (disrupt == 0) disrupt = (uint32_t)(long)raddr; @@ -156,6 +158,21 @@ ct->ct_upcallrefs = 0; if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) { + /* Check for a timeout on the soconnect(). */ + bzero(&sopt, sizeof(sopt)); + sopt.sopt_dir = SOPT_GET; + sopt.sopt_level = SOL_SOCKET; + sopt.sopt_name = SO_SNDTIMEO; + sopt.sopt_val = &tv; + sopt.sopt_valsize = sizeof(tv); + error = sogetopt(so, &sopt); + timo = 0; + /* + * The code that sets SO_SNDTIMEO only does so for timeouts + * of 1sec or greater. + */ + if (error == 0 && tv.tv_sec > 0 && tv.tv_usec >= 0) + timo = tvtohz(&tv); error = soconnect(so, raddr, curthread); SOCK_LOCK(so); interrupted = 0; @@ -165,9 +182,10 @@ while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { error = msleep(&so->so_timeo, SOCK_MTX(so), - sleep_flag, "connec", 0); + sleep_flag, "connec", timo); if (error) { - if (error == EINTR || error == ERESTART) + if (error == EINTR || error == ERESTART || + error == EAGAIN) interrupted = 1; break; }