From 05c629f778acaf7b83583426c0138ef463fb41af Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Dec 1997 12:33:15 +0000 Subject: [PATCH] I think I've (finally) fixed the problem with rsync periodically freezing when used with ssh. The problem is really the ssh use of blocking calls. rsync has had a fix for this for a while which relies on using non-blocking calls itself and then reading any data from the incoming fd when trying to write, thus ensuring that the incoming fd doesn't get full. The problem was the the incoming fd wasn't added to the select statement, which meant that new data arriving on the fd only got read when the select timed out, which happens every 10 seconds. Thus things could slow to a crawl! The incoming fd is now in the select call, and this seems to fix the problem. --- io.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/io.c b/io.c index e7292df4..51fc0cb0 100644 --- a/io.c +++ b/io.c @@ -62,6 +62,8 @@ static void read_check(int f) { int n; + if (f == -1) return; + if (read_buffer_len == 0) { read_buffer_p = read_buffer; } @@ -69,6 +71,9 @@ static void read_check(int f) if ((n=num_waiting(f)) <= 0) return; + /* things could deteriorate if we read in really small chunks */ + if (n < 10) n = 1024; + if (read_buffer_p != read_buffer) { memmove(read_buffer,read_buffer_p,read_buffer_len); read_buffer_p = read_buffer; @@ -95,10 +100,13 @@ static int readfd(int fd,char *buffer,int N) { int ret; int total=0; + + if (read_buffer_len < N) + read_check(buffer_f_in); while (total < N) { - if (read_buffer_len > 0) { + if (read_buffer_len > 0 && buffer_f_in == fd) { ret = MIN(read_buffer_len,N-total); memcpy(buffer+total,read_buffer_p,ret); read_buffer_p += ret; @@ -228,7 +236,8 @@ int read_write(int fd_in,int fd_out,int size) static int writefd(int fd,char *buf,int len) { int total = 0; - fd_set fds; + fd_set w_fds, r_fds; + int fd_count; struct timeval tv; if (buffer_f_in == -1) @@ -245,11 +254,18 @@ static int writefd(int fd,char *buf,int len) if (ret == -1) { read_check(buffer_f_in); - FD_ZERO(&fds); - FD_SET(fd,&fds); + fd_count = fd+1; + FD_ZERO(&w_fds); + FD_ZERO(&r_fds); + FD_SET(fd,&w_fds); + if (buffer_f_in != -1) { + FD_SET(buffer_f_in,&r_fds); + if (buffer_f_in > fd) + fd_count = buffer_f_in+1; + } tv.tv_sec = BLOCKING_TIMEOUT; tv.tv_usec = 0; - select(fd+1,NULL,&fds,NULL,&tv); + select(fd_count,buffer_f_in == -1? NULL: &r_fds,&w_fds,NULL,&tv); } else { total += ret; } -- 2.34.1