rsync 2.5.4 (probably 2.5.5 too) server handles SIGPIPE very poorly

Jonathan Kamens jik at kamens.brookline.ma.us
Tue May 28 07:26:02 EST 2002


(I am not on the rsync mailing list, so if you send a response to this
message to the list, please be sure to CC me.)

I first reported this bug go Red Hat in
<URL:https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=65350>.

If you run rsync with a subshell through ssh.com's ssh and sshd and
then kill the client with ctrl-C, the rsync server process running on
the remote machine grows without bound and eventually completely hoses
the machine.

After some debugging, I determined this to be the problem (as reported
in the Red Hat bug ticket noted above):

  When the client rsync and ssh exit, and thus sshd on the other end
  exits, and then the server rsync tries to write to the client, it
  gets SIGPIPE.  Alas, SIGPIPE is being ignored, because, quoting a
  comment in the rsync source code, "Ignore SIGPIPE; we consistently
  check error codes and will see the EPIPE."

  The comment is wrong; it does *not* see the SIGPIPE.  What happens
  is that as a result of the SIGPIPE, exit_cleanup gets called.
  That's a macro which calls _exit_cleanup.  That calls log_exit That
  calls rwrite.  Rwrite tries to write an error to stderr, but that
  fails because of (you guessed it!) SIGPIPE, and so rwrite calls
  exit_cleanup.  Presto, an infinite loop is born.

  The most straightforward fix I came up with is to modify rwrite so
  that it doesn't actually try to write the error if the FILE to which
  the error has been written is showing a true error condition
  (checked with ferror).  I will attach a patch.

  I suspect that the rsync server running under openssh doesn't have
  this problem because openssh sshd causes it it to get a SIGHUP
  whereas the ssh.com version of sshd does not.  That's just a guess
  though.

Here's the patch I submitted:

*** log.c~	Mon Feb 18 14:51:12 2002
--- log.c	Tue May 28 10:05:30 2002
***************
*** 276,284 ****
  
  	if (!f) exit_cleanup(RERR_MESSAGEIO);
  
! 	if (fwrite(buf, len, 1, f) != 1) exit_cleanup(RERR_MESSAGEIO);
  
! 	if (buf[len-1] == '\r' || buf[len-1] == '\n') fflush(f);
  }
  		
  
--- 276,286 ----
  
  	if (!f) exit_cleanup(RERR_MESSAGEIO);
  
! 	if (! ferror(f)) {
! 		if (fwrite(buf, len, 1, f) != 1) exit_cleanup(RERR_MESSAGEIO);
  
! 		if (buf[len-1] == '\r' || buf[len-1] == '\n') fflush(f);
! 	}
  }
  		
  
This strikes me as a pretty serious bug; I hope you will consider
releasing a patch release with this fix (or an equivalent one, if you
don't like how I fixed it) soon.

Thank you,

  Jonathan Kamens




More information about the rsync mailing list