s->rep->flags |= CF_READ_DONTWAIT;
- if (unlikely(b_alloc(&s->req->buf) == NULL))
- goto out_fail_req_buf; /* no memory */
-
- if (unlikely(b_alloc(&s->rep->buf) == NULL))
- goto out_fail_rep_buf; /* no memory */
-
/* it is important not to call the wakeup function directly but to
* pass through task_wakeup(), because this one knows how to apply
* priorities to tasks.
return s;
/* Error unrolling */
- out_fail_rep_buf:
- b_free(&s->req->buf);
- out_fail_req_buf:
- pool_free2(pool2_channel, s->rep);
out_fail_rep:
pool_free2(pool2_channel, s->req);
out_fail_req:
s->rep->wex = TICK_ETERNITY;
s->rep->analyse_exp = TICK_ETERNITY;
- if (unlikely(b_alloc(&s->req->buf) == NULL))
- goto out_free_rep; /* no memory */
-
- if (unlikely(b_alloc(&s->rep->buf) == NULL))
- goto out_free_req_buf; /* no memory */
-
txn = &s->txn;
/* Those variables will be checked and freed if non-NULL in
* session.c:session_free(). It is important that they are
* finished (=0, eg: monitoring), in both situations,
* we can release everything and close.
*/
- goto out_free_rep_buf;
+ goto out_free_rep;
}
/* if logs require transport layer information, note it on the connection */
return 1;
/* Error unrolling */
- out_free_rep_buf:
- b_free(&s->rep->buf);
- out_free_req_buf:
- b_free(&s->req->buf);
out_free_rep:
pool_free2(pool2_channel, s->rep);
out_free_req:
goto update_exp_and_leave;
}
+ /* below we may emit error messages so we have to ensure that we have
+ * our buffers properly allocated.
+ */
+ if (!session_alloc_buffers(s)) {
+ /* No buffer available, we've been subscribed to the list of
+ * buffer waiters, let's wait for our turn.
+ */
+ goto update_exp_and_leave;
+ }
+
/* 1b: check for low-level errors reported at the stream interface.
* First we check if it's a retryable error (in which case we don't
* want to tell the buffer). Otherwise we report the error one level
if ((si_applet_call(s->req->cons) | si_applet_call(s->rep->cons)) != 0) {
if (task_in_rq(t)) {
t->expire = TICK_ETERNITY;
+ session_release_buffers(s);
return t;
}
}
if (!tick_isset(t->expire))
ABORT_NOW();
#endif
+ session_release_buffers(s);
return t; /* nothing more to do */
}
}
if (si->ib->flags & CF_READ_ACTIVITY)
si->ib->flags &= ~CF_READ_DONTWAIT;
+
+ session_release_buffers(si_sess(si));
return 0;
}
chn->pipe = NULL;
}
+ /* now we'll need a buffer */
+ if (!session_alloc_recv_buffer(si_sess(si), &chn->buf)) {
+ si->flags |= SI_FL_WAIT_ROOM;
+ goto end_recv;
+ }
+
/* Important note : if we're called with POLL_IN|POLL_HUP, it means the read polling
* was enabled, which implies that the recv buffer was not full. So we have a guarantee
* that if such an event is not handled above in splice, it will be handled here by
}
} /* while !flags */
- if (conn->flags & CO_FL_ERROR)
- return;
-
if (cur_read) {
if ((chn->flags & (CF_STREAMER | CF_STREAMER_FAST)) &&
(cur_read <= chn->buf->size / 2)) {
chn->last_read = now_ms;
}
+ end_recv:
+ if (conn->flags & CO_FL_ERROR)
+ return;
+
if (conn_data_read0_pending(conn))
/* connection closed */
goto out_shutdown_r;