[SCM] The rsync repository. - branch master updated

Rsync CVS commit messages rsync-cvs at lists.samba.org
Sun May 26 17:23:48 MDT 2013


The branch, master has been updated
       via  9bf0658 Improve logic of code vs exit_code (etc.) in cleanup.
       via  5b46454 Forward a MSG_ERROR_EXIT value to generator too. Fixes bug 9882.
       via  d4070db Avoid I/O via signal-handler thread.
      from  cb784f1 Improve iconvbufs() to do more buffer size checks.

;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 9bf065860fa47995eb946a68ee4803d30123da9c
Author: Wayne Davison <wayned at samba.org>
Date:   Sun May 26 16:18:49 2013 -0700

    Improve logic of code vs exit_code (etc.) in cleanup.

commit 5b464543648c08538389a4dfeb0b6b60049bd084
Author: Wayne Davison <wayned at samba.org>
Date:   Sun May 26 16:10:57 2013 -0700

    Forward a MSG_ERROR_EXIT value to generator too.
    Fixes bug 9882.

commit d4070db6312c4b38980ad165732d6beaaa0c06b3
Author: Wayne Davison <wayned at samba.org>
Date:   Sun May 26 14:52:50 2013 -0700

    Avoid I/O via signal-handler thread.
    
    The cleanup code will try to flush the output buffer in some
    circumstances, which is not valid if we're handling an async signal
    (since it might have interrupted some partial I/O in the main thread).
    These signals now set a flag and try to let the main I/O handler take
    care of the exit strategy.  Fixes a protocol error that could happen
    when trying to exit after a kill signal.

-----------------------------------------------------------------------

Summary of changes:
 cleanup.c |   48 +++++++++++++++++++++++++++---------------------
 io.c      |   14 +++++++++++++-
 rsync.c   |   15 +++++++++++++++
 3 files changed, 55 insertions(+), 22 deletions(-)


Changeset truncated at 500 lines:

diff --git a/cleanup.c b/cleanup.c
index 9de6eab..d84abb5 100644
--- a/cleanup.c
+++ b/cleanup.c
@@ -34,6 +34,7 @@ extern char *partial_dir;
 extern char *logfile_name;
 
 BOOL shutting_down = False;
+BOOL flush_ok_after_signal = False;
 
 #ifdef HAVE_SIGACTION
 static struct sigaction sigact;
@@ -101,15 +102,15 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
 	static int switch_step = 0;
 	static int exit_code = 0, exit_line = 0;
 	static const char *exit_file = NULL;
-	static int unmodified_code = 0;
+	static int first_code = 0;
 
 	SIGACTION(SIGUSR1, SIG_IGN);
 	SIGACTION(SIGUSR2, SIG_IGN);
 
-	if (exit_code) { /* Preserve first exit info when recursing. */
-		code = exit_code;
-		file = exit_file;
-		line = exit_line;
+	if (!exit_code) { /* Preserve first error exit info when recursing. */
+		exit_code = code;
+		exit_file = file;
+		exit_line = line < 0 ? -line : line;
 	}
 
 	/* If this is the exit at the end of the run, the server side
@@ -123,9 +124,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
 #include "case_N.h" /* case 0: */
 		switch_step++;
 
-		exit_code = unmodified_code = code;
-		exit_file = file;
-		exit_line = line;
+		first_code = code;
 
 		if (output_needs_newline) {
 			fputc('\n', stdout);
@@ -147,8 +146,8 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
 			int pid = wait_process(cleanup_child_pid, &status, WNOHANG);
 			if (pid == cleanup_child_pid) {
 				status = WEXITSTATUS(status);
-				if (status > code)
-					code = exit_code = status;
+				if (status > exit_code)
+					exit_code = status;
 			}
 		}
 
@@ -182,7 +181,12 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
 #include "case_N.h"
 		switch_step++;
 
-		if (!code || am_server || am_receiver)
+		if (flush_ok_after_signal) {
+			flush_ok_after_signal = False;
+			if (code == RERR_SIGNAL)
+				io_flush(FULL_FLUSH);
+		}
+		if (!exit_code && !code)
 			io_flush(FULL_FLUSH);
 
 		/* FALLTHROUGH */
@@ -191,7 +195,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
 
 		if (cleanup_fname)
 			do_unlink(cleanup_fname);
-		if (code)
+		if (exit_code)
 			kill_all(SIGUSR1);
 		if (cleanup_pid && cleanup_pid == getpid()) {
 			char *pidf = lp_pid_file();
@@ -199,20 +203,22 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
 				unlink(lp_pid_file());
 		}
 
-		if (code == 0) {
+		if (exit_code == 0) {
+			if (code)
+				exit_code = code;
 			if (io_error & IOERR_DEL_LIMIT)
-				code = exit_code = RERR_DEL_LIMIT;
+				exit_code = RERR_DEL_LIMIT;
 			if (io_error & IOERR_VANISHED)
-				code = exit_code = RERR_VANISHED;
+				exit_code = RERR_VANISHED;
 			if (io_error & IOERR_GENERAL || got_xfer_error)
-				code = exit_code = RERR_PARTIAL;
+				exit_code = RERR_PARTIAL;
 		}
 
 		/* If line < 0, this exit is after a MSG_ERROR_EXIT event, so
 		 * we don't want to output a duplicate error. */
-		if ((code && line > 0)
+		if ((exit_code && line > 0)
 		 || am_daemon || (logfile_name && (am_server || !INFO_GTE(STATS, 1))))
-			log_exit(code, file, line);
+			log_exit(exit_code, exit_file, exit_line);
 
 		/* FALLTHROUGH */
 #include "case_N.h"
@@ -222,7 +228,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
 			rprintf(FINFO,
 				"[%s] _exit_cleanup(code=%d, file=%s, line=%d): "
 				"about to call exit(%d)\n",
-				who_am_i(), unmodified_code, file, line, code);
+				who_am_i(), first_code, exit_file, exit_line, exit_code);
 		}
 
 		/* FALLTHROUGH */
@@ -245,7 +251,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
 #include "case_N.h"
 		switch_step++;
 
-		if (am_server && code)
+		if (am_server && exit_code)
 			msleep(100);
 		close_all();
 
@@ -254,7 +260,7 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
 		break;
 	}
 
-	exit(code);
+	exit(exit_code);
 }
 
 void cleanup_disable(void)
diff --git a/io.c b/io.c
index 096225f..2c69b82 100644
--- a/io.c
+++ b/io.c
@@ -57,6 +57,7 @@ extern int protocol_version;
 extern int remove_source_files;
 extern int preserve_hard_links;
 extern BOOL extra_flist_sending_enabled;
+extern BOOL flush_ok_after_signal;
 extern struct stats stats;
 extern struct file_list *cur_flist;
 #ifdef ICONV_OPTION
@@ -73,6 +74,7 @@ BOOL flist_receiving_enabled = False;
 
 /* Ignore an EOF error if non-zero. See whine_about_eof(). */
 int kluge_around_eof = 0;
+int got_kill_signal = -1; /* is set to 0 only after multiplexed I/O starts */
 
 int sock_f_in = -1;
 int sock_f_out = -1;
@@ -852,6 +854,12 @@ static char *perform_io(size_t needed, int flags)
 			}
 		}
 
+		if (got_kill_signal > 0) {
+			got_kill_signal = -1;
+			flush_ok_after_signal = True;
+			exit_cleanup(RERR_SIGNAL);
+		}
+
 		/* We need to help prevent deadlock by doing what reading
 		 * we can whenever we are here trying to write. */
 		if (IN_MULTIPLEXED_AND_READY && !(flags & PIO_NEED_INPUT)) {
@@ -1605,7 +1613,7 @@ static void read_a_msg(void)
 				io_flush(FULL_FLUSH);
 			}
 		} else if (protocol_version >= 31) {
-			if (am_generator) {
+			if (am_generator || am_receiver) {
 				if (DEBUG_GTE(EXIT, 3)) {
 					rprintf(FINFO, "[%s] sending MSG_ERROR_EXIT with exit_code %d\n",
 						who_am_i(), val);
@@ -2282,6 +2290,7 @@ void io_start_multiplex_out(int fd)
 
 	iobuf.out_empty_len = 4; /* See also OUT_MULTIPLEXED */
 	io_start_buffering_out(fd);
+	got_kill_signal = 0;
 
 	iobuf.raw_data_header_pos = iobuf.out.pos + iobuf.out.len;
 	iobuf.out.len += 4;
@@ -2329,6 +2338,9 @@ int io_end_multiplex_out(int mode)
 
 	iobuf.out.len = 0;
 	iobuf.out_empty_len = 0;
+	if (got_kill_signal > 0) /* Just in case... */
+		exit_cleanup(RERR_SIGNAL);
+	got_kill_signal = -1;
 
 	return ret;
 }
diff --git a/rsync.c b/rsync.c
index cf21009..1f9b029 100644
--- a/rsync.c
+++ b/rsync.c
@@ -42,6 +42,7 @@ extern int am_generator;
 extern int am_starting_up;
 extern int allow_8bit_chars;
 extern int protocol_version;
+extern int got_kill_signal;
 extern int inc_recurse;
 extern int inplace;
 extern int flist_eof;
@@ -599,6 +600,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
 	return updated;
 }
 
+/* This is only called for SIGINT, SIGHUP, and SIGTERM. */
 RETSIGTYPE sig_int(int sig_num)
 {
 	/* KLUGE: if the user hits Ctrl-C while ssh is prompting
@@ -610,10 +612,23 @@ RETSIGTYPE sig_int(int sig_num)
 	 * not ssh waiting for a password, then this tiny delay
 	 * shouldn't hurt anything. */
 	msleep(400);
+
 	/* If we're an rsync daemon listener (not a daemon server),
 	 * we'll exit with status 0 if we received SIGTERM. */
 	if (am_daemon && !am_server && sig_num == SIGTERM)
 		exit_cleanup(0);
+
+	/* If the signal arrived on the server side (or for the receiver
+	 * process on the client), we want to try to do a controlled shutdown
+	 * that lets the client side (generator process) know what happened.
+	 * To do this, we set a flag and let the normal process handle the
+	 * shutdown.  We only attempt this if multiplexed IO is in effect and
+	 * we didn't already set the flag. */
+	if (!got_kill_signal && (am_server || am_receiver)) {
+		got_kill_signal = sig_num;
+		return;
+	}
+
 	exit_cleanup(RERR_SIGNAL);
 }
 


-- 
The rsync repository.


More information about the rsync-cvs mailing list