if during recv we received an error, then propagate that to the caller.
otherwise, do time out check. also do timeout check if the thread's xid
didn't match received xid (making sure we'll timeout if we have a starving
thread that will never receive a reply)
if we receive an rpc_autherr, just recreate a new rpc client as well
as the rpc auth structure. as it ties into the recovery and handles
that only one thread recovers and reestablishes the rpc auth context.
in theory, reestablishing rpc client does not necessitate new rpc auth
context. we really need to restablish one only if we get rpc autherr. however,
it simplifies the code not to introduce a different synchronization
mechanism for rpc auth in addition to the rpc one.
once libtirpc blocking recv was changed to a polling receive,
we no longer had a timeout mechanims on waiting for a reply.
solution: save a timestamp before the recv call, on each async recv return
check if the time lapsed does not exceed the timeout value. when timeout
is reach, return TIMEDOUT rpc error.
we already drop the lock between sending and receiving the rpc packets. now making it so that receive doesn't block for too long (ie 100ms) before unlocking the socket. this is needed for the callback. original rpc is sent and it triggers a callback from the server. we fork another thread to handle it, ie it needs to send a deleg_return rpc. if original rpc gets control and blocks on trying to receive its reply, it'll timeout and original rpc will return an error. instead we need to not block for long and allow the deleg_return to go thru so that the server can reply successfully to the original rpc.
we were checking for error result of send_null but not setting
status, then going to "out_unlock" and since status is NO_ERROR
trying to send bind_conn_to_session