diff options
author | Wayne Davison <wayne@opencoder.net> | 2020-06-04 14:11:07 -0700 |
---|---|---|
committer | Wayne Davison <wayne@opencoder.net> | 2020-06-04 14:20:51 -0700 |
commit | 01b9bbb0f94e4ddd4b1e3ad678b220ca09bc0ad0 (patch) | |
tree | 8370b062fc3e6604fe101aa151e22124abceb887 /io.c | |
parent | 852a0b29c3ae08c28b3b0a455869b29fde34740c (diff) | |
download | rsync-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.c | 15 |
1 files changed, 12 insertions, 3 deletions
@@ -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: |