went back to non-blokcing IO
authorAndrew Tridgell <tridge@samba.org>
Thu, 30 Mar 2000 14:15:00 +0000 (14:15 +0000)
committerAndrew Tridgell <tridge@samba.org>
Thu, 30 Mar 2000 14:15:00 +0000 (14:15 +0000)
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
clientserver.c
io.c
main.c
rsync.h
util.c

index d35ec3f..03a77f8 100644 (file)
@@ -11,3 +11,4 @@
 #undef HAVE_GETOPT_LONG
 #undef REPLACE_INET_NTOA
 #undef HAVE_GETTIMEOFDAY_TZ
+#undef HAVE_SOCKETPAIR
index df847ff..7518e3e 100644 (file)
@@ -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 6cdbe6b..6a55576 100644 (file)
--- 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 0c4f2cd..f7e52be 100644 (file)
--- 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 a4b7e81..f9f0fd4 100644 (file)
--- 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 a0e2707..03a626e 100644 (file)
--- a/util.c
+++ b/util.c
 
 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;
 }