Also, looking at this code, I see that connection_read_to_buf has exactly one caller, which first calls it with -1 in *max_to_read, and then keeps calling with *max_to_read unchanged from however connection_read_to_buf left it.
With this in mind, the part of the code that does:
*max_to_read = at_most - n_read;
seems like it's probably going to be wrong. Maybe instead we should do something like:
diff --git a/src/or/connection.c b/src/or/connection.cindex 223bbd9..5850e76 100644--- a/src/or/connection.c+++ b/src/or/connection.c@@ -2866,9 +2866,10 @@ connection_read_to_buf(connection_t *conn, ssize_t *max_to_read, size_t slack_in_buf, more_to_read; size_t n_read = 0, n_written = 0;- if (at_most == -1) { /* we need to initialize it */+ if (at_most < 0) { /* we need to initialize it */ /* how many bytes are we allowed to read? */ at_most = connection_bucket_read_limit(conn, approx_time());+ *max_to_readd = at_most; } slack_in_buf = buf_slack(conn->inbuf);@@ -2979,7 +2980,7 @@ connection_read_to_buf(connection_t *conn, ssize_t *max_to_read, if (n_read > 0) { /* change *max_to_read */- *max_to_read = at_most - n_read;+ *max_to_read -= n_read; /* Update edge_conn->n_read */ if (conn->type == CONN_TYPE_AP) {
+ if (at_most < 0) { /* we need to initialize it */ /* how many bytes are we allowed to read? */ at_most = connection_bucket_read_limit(conn, approx_time());+ *max_to_read = at_most; }
Leads to extra call of connection_read_to_buf() if recv will return EWOULDBLOCK.
It probably better to refactor connection_handle_read_impl() with no loop.