Signed and unsigned values were compared thus making the code path where ret = -1 being interpreted as ret > len == true thus not cleaning up the relayd.
This patch simplifies the read subbuffer mmap operation since lttng_write() now provides a guarantee that the return data is either equal to the count passed or less which the later means the endpoint has stop working. Signed-off-by: David Goulet <[email protected]> --- src/common/consumer.c | 82 +++++++++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/src/common/consumer.c b/src/common/consumer.c index 36ec024..59d4366 100644 --- a/src/common/consumer.c +++ b/src/common/consumer.c @@ -1451,7 +1451,7 @@ ssize_t lttng_consumer_on_read_subbuffer_mmap( { unsigned long mmap_offset; void *mmap_base; - ssize_t ret = 0, written = 0; + ssize_t ret = 0, written = 0, signed_len; off_t orig_offset = stream->out_fd_offset; /* Default is on the disk */ int outfd = stream->out_fd; @@ -1584,44 +1584,56 @@ ssize_t lttng_consumer_on_read_subbuffer_mmap( } } - while (len > 0) { - ret = lttng_write(outfd, mmap_base + mmap_offset, len); - DBG("Consumer mmap write() ret %zd (len %lu)", ret, len); - if (ret < len) { - /* - * This is possible if the fd is closed on the other side (outfd) - * or any write problem. It can be verbose a bit for a normal - * execution if for instance the relayd is stopped abruptly. This - * can happen so set this to a DBG statement. - */ - DBG("Error in file write mmap"); - if (written == 0) { - written = -errno; - } - /* Socket operation failed. We consider the relayd dead */ - if (errno == EPIPE || errno == EINVAL) { - relayd_hang_up = 1; - goto write_error; - } - goto end; - } else if (ret > len) { - PERROR("Error in file write (ret %zd > len %lu)", ret, len); - written += ret; - goto end; + /* + * Set the len value to a signed value so the if/else statement can + * evaluate it against the signed returned value from lttng_write since + * -1 can be returned indicating a communication failure. + */ + signed_len = len; + + /* + * This call guarantee that len or less is returned. It's impossible to + * receive a ret value that is bigger than len. + */ + ret = lttng_write(outfd, mmap_base + mmap_offset, len); + DBG("Consumer mmap write() ret %zd (len %lu)", ret, len); + if (ret != signed_len) { + /* + * Report error to caller if nothing was written else at least send the + * amount written. + */ + if (ret < 0) { + written = -errno; } else { - len -= ret; - mmap_offset += ret; + written = ret; } - /* This call is useless on a socket so better save a syscall. */ - if (!relayd) { - /* This won't block, but will start writeout asynchronously */ - lttng_sync_file_range(outfd, stream->out_fd_offset, ret, - SYNC_FILE_RANGE_WRITE); - stream->out_fd_offset += ret; + /* Socket operation failed. We consider the relayd dead */ + if (errno == EPIPE || errno == EINVAL) { + /* + * This is possible if the fd is closed on the other side + * (outfd) or any write problem. It can be verbose a bit for a + * normal execution if for instance the relayd is stopped + * abruptly. This can happen so set this to a DBG statement. + */ + DBG("Consumer mmap write detected relayd hang up"); + relayd_hang_up = 1; + goto write_error; } - stream->output_written += ret; - written += ret; + + /* Unhandled error, print it and stop function right now. */ + PERROR("Error in write mmap (ret %zd < len %lu)", ret, len); + goto end; + } + stream->output_written += ret; + written = ret; + + /* This call is useless on a socket so better save a syscall. */ + if (!relayd) { + /* This won't block, but will start writeout asynchronously */ + lttng_sync_file_range(outfd, stream->out_fd_offset, len, + SYNC_FILE_RANGE_WRITE); + stream->out_fd_offset += len; } lttng_consumer_sync_trace_file(stream, orig_offset); -- 1.8.5.3 _______________________________________________ lttng-dev mailing list [email protected] http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
