From f0359dd00d60d72c4b3dec85de8e490692f6015c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 30 Mar 2000 14:15:00 +0000 Subject: [PATCH] went back to non-blokcing IO it looks like ssh is willing to accept a non-blocking fd when used as a transport, this seems to avoid the Solaris socketpair bug --- acconfig.h | 1 + clientserver.c | 2 +- io.c | 12 +++++++++++- main.c | 8 ++++++++ rsync.h | 9 +++++++++ util.c | 40 ++++++++++++++++++++++++++++++++++++---- 6 files changed, 66 insertions(+), 6 deletions(-) diff --git a/acconfig.h b/acconfig.h index d35ec3fb..03a77f8c 100644 --- a/acconfig.h +++ b/acconfig.h @@ -11,3 +11,4 @@ #undef HAVE_GETOPT_LONG #undef REPLACE_INET_NTOA #undef HAVE_GETTIMEOFDAY_TZ +#undef HAVE_SOCKETPAIR diff --git a/clientserver.c b/clientserver.c index df847ffc..7518e3e1 100644 --- a/clientserver.c +++ b/clientserver.c @@ -363,7 +363,7 @@ static int start_daemon(int fd) set_socket_options(fd,"SO_KEEPALIVE"); set_socket_options(fd,lp_socket_options()); - + set_nonblocking(fd); io_printf(fd,"@RSYNCD: %d\n", PROTOCOL_VERSION); diff --git a/io.c b/io.c index 6cdbe6bf..6a55576d 100644 --- a/io.c +++ b/io.c @@ -159,6 +159,11 @@ static int read_timeout(int fd, char *buf, int len) continue; } + if (n == -1 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { + continue; + } + if (n == 0) { if (eof_error) { @@ -364,12 +369,17 @@ static void writefd_unbuffered(int fd,char *buf,int len) if (FD_ISSET(fd, &w_fds)) { int ret, n = len-total; - ret = write(fd,buf+total,n?n:1); + ret = write(fd,buf+total,n); if (ret == -1 && errno == EINTR) { continue; } + if (ret == -1 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { + continue; + } + if (ret <= 0) { rprintf(FERROR,"erroring writing %d bytes - exiting\n", len); exit_cleanup(RERR_STREAMIO); diff --git a/main.c b/main.c index 0c4f2cda..f7e52bed 100644 --- a/main.c +++ b/main.c @@ -417,6 +417,9 @@ void start_server(int f_in, int f_out, int argc, char *argv[]) setup_protocol(f_out, f_in); + set_nonblocking(f_in); + set_nonblocking(f_out); + if (remote_version >= 23) io_start_multiplex_out(f_out); @@ -440,6 +443,9 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[]) extern int list_only; extern int remote_version; + set_nonblocking(f_in); + set_nonblocking(f_out); + setup_protocol(f_out,f_in); if (remote_version >= 23) @@ -695,6 +701,8 @@ int main(int argc,char *argv[]) #endif if (am_server) { + set_nonblocking(STDIN_FILENO); + set_nonblocking(STDOUT_FILENO); start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv); } diff --git a/rsync.h b/rsync.h index a4b7e812..f9f0fd4f 100644 --- a/rsync.h +++ b/rsync.h @@ -457,6 +457,15 @@ extern int errno; #define S_ISREG(mode) (((mode) & (_S_IFMT)) == (_S_IFREG)) #endif +/* work out what fcntl flag to use for non-blocking */ +#ifdef O_NONBLOCK +# define NONBLOCK_FLAG O_NONBLOCK +#elif defined(SYSV) +# define NONBLOCK_FLAG O_NDELAY +#else +# define NONBLOCK_FLAG FNDELAY +#endif + #define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) || S_ISFIFO(mode)) diff --git a/util.c b/util.c index a0e2707e..03a626eb 100644 --- a/util.c +++ b/util.c @@ -26,15 +26,47 @@ extern int verbose; -/* create a file descriptor - like pipe() but use socketpair if - possible (because of blocking issues on pipes */ + +/**************************************************************************** +Set a fd into nonblocking mode. Uses POSIX O_NONBLOCK if available, +else +if SYSV use O_NDELAY +if BSD use FNDELAY +****************************************************************************/ +void set_nonblocking(int fd) +{ + int val; + + if((val = fcntl(fd, F_GETFL, 0)) == -1) + return; + if (!(val & NONBLOCK_FLAG)) { + val |= NONBLOCK_FLAG; + fcntl(fd, F_SETFL, val); + } +} + + +/* create a file descriptor pair - like pipe() but use socketpair if + possible (because of blocking issues on pipes) + + always set non-blocking + */ int fd_pair(int fd[2]) { + int ret; + #if HAVE_SOCKETPAIR - return socketpair(AF_UNIX, SOCK_STREAM, 0, fd); + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd); #else - return pipe(fd); + ret = pipe(fd); #endif + + if (ret == 0) { + set_nonblocking(fd[0]); + set_nonblocking(fd[1]); + } + + return ret; } -- 2.34.1