rconn: Reconnect reliably when underlying vconn reports error.
When a vconn reports an error, the rconn would not reliably reconnect.
In particular, if the error was reported after the call to rconn_run()
but before rconn_run_wait() was called, then the state's "run" routine
would not set min_timeout properly, leading to a potentially arbitrarily
long wait (depending on what other events were going on in) until the
state's "run" routine was called again.
The fix is to have a separate per-state "timeout" routine to compute
when the state needs to be re-entered.
This commit was tested using the following change to randomly inject
errors:
@@ -554,11 +554,16 @@
static int
try_send(struct rconn *rc)
{
int retval = 0;
struct buffer *next = rc->txq.head->next;
- retval = vconn_send(rc->vconn, rc->txq.head);
+ if (!random_range(1000)) {
+ fprintf(stderr, "injecting ECONNRESET\n");
+ retval = ECONNRESET;
+ } else {
+ retval = vconn_send(rc->vconn, rc->txq.head);
+ }
if (retval) {
if (retval != EAGAIN) {
disconnect(rc, retval);
}
return retval;