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)

Attachment: signature.asc
Description: Digital signature

Reply via email to