On Wed, Aug 19, 2009 at 01:38:32AM +0200, Arnaud Cornet wrote: > Here is a quite hackish way to deal with the problem without rewriting > much of the event system. > We hack the message we want to send to the wire directly in the case of > partial writes. > > That allows us to keep the buffer in the event system and not block in a > sleep or loop. > > If you have a bad connection, can you please test the patch?
To simulate a bad connection, open two IRC clients, point them both at the same bip proxy, connect to a big IRC network, kill -STOP one of them, and type '/list' into the other, or join a bunch of large channels and run "/who #channelname" on them. The STOPped client will block pretty quickly, and with unmodified bip, so does the non-STOPped client. I applied your patch and tested it. There's one bug left: when we are looping with the write(), we want the loop to repeat if the write is successful but incomplete, or if the error is EINTR; otherwise, this happens: 1. We get a partial write (count > 0), so we exit the while loop with write() in it, 2. "tcount < size", so we enter that if statement body, 3. "count < 0 && (errno == EAGAIN || errno == EINPROGRESS)" is not true because count > 0, so we (incorrectly) don't enter the if statement body with the memmove() call and "return WRITE_KEEP" statement, 4. cn_is_connected(cn), so we enter that if statement's body and close the connection. The symptom of all this is that a '/list' command drops client connections when connected to a large (e.g. Freenode or OFTC) IRC net when the upstream connection is faster than the downstream ones. Once the following patch is applied on top of yours, though, it works like a champ! I am a bit worried that it will run my proxy server out of RAM if there is an extended network problem; however, my server has more RAM available than all of space consumed by my IRC logs combined, so I'll probably notice the process growing well before it becomes an issue. diff --git a/src/connection.c b/src/connection.c index 2e313e5..f89a2f7 100644 --- a/src/connection.c +++ b/src/connection.c @@ -243,7 +243,7 @@ static int _write_socket(connection_t *cn, char *message) if (tcount == size) break; } - } while (count < 0 && errno == EINTR); + } while (count > 0 || errno == EINTR); #if 0 if (count <= 0 && tcount > 0)
signature.asc
Description: Digital signature