summaryrefslogtreecommitdiff
path: root/io.c
diff options
context:
space:
mode:
authorWayne Davison <wayne@opencoder.net>2020-06-04 14:11:07 -0700
committerWayne Davison <wayne@opencoder.net>2020-06-04 14:20:51 -0700
commit01b9bbb0f94e4ddd4b1e3ad678b220ca09bc0ad0 (patch)
tree8370b062fc3e6604fe101aa151e22124abceb887 /io.c
parent852a0b29c3ae08c28b3b0a455869b29fde34740c (diff)
downloadrsync-01b9bbb0f94e4ddd4b1e3ad678b220ca09bc0ad0.tar.gz
Avoid a deadlock due to huge amounts of verbose messages.
Allow the receiver to increase their iobuf.msg xbuf if it fills up. This ensures that the receiver will never block trying to output a message, and thus it will always drain the data from the sender and keep the whole thing from clogging up.
Diffstat (limited to 'io.c')
-rw-r--r--io.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/io.c b/io.c
index 999c34e5..ceff3784 100644
--- a/io.c
+++ b/io.c
@@ -954,8 +954,17 @@ int send_msg(enum msgcode code, const char *buf, size_t len, int convert)
} else
#endif
needed = len + 4 + 3;
- if (iobuf.msg.len + needed > iobuf.msg.size)
- perform_io(needed, PIO_NEED_MSGROOM);
+ if (iobuf.msg.len + needed > iobuf.msg.size) {
+ if (!am_receiver)
+ perform_io(needed, PIO_NEED_MSGROOM);
+ else { /* We allow the receiver to increase their iobuf.msg size to avoid a deadlock. */
+ size_t old_size = iobuf.msg.size;
+ restore_iobuf_size(&iobuf.msg);
+ realloc_xbuf(&iobuf.msg, iobuf.msg.size * 2);
+ if (iobuf.msg.pos + iobuf.msg.len > old_size)
+ memcpy(iobuf.msg.buf + old_size, iobuf.msg.buf, iobuf.msg.pos + iobuf.msg.len - old_size);
+ }
+ }
pos = iobuf.msg.pos + iobuf.msg.len; /* Must be set after any flushing. */
if (pos >= iobuf.msg.size)
@@ -1176,7 +1185,7 @@ int read_line(int fd, char *buf, size_t bufsiz, int flags)
#ifdef ICONV_OPTION
if (flags & RL_CONVERT && iconv_buf.size < bufsiz)
- realloc_xbuf(&iconv_buf, bufsiz + 1024);
+ realloc_xbuf(&iconv_buf, ROUND_UP_1024(bufsiz) + 1024);
#endif
start: