From 1c1d572f5cf7eb9a5eab0feaef8b745c45b6dad0 Mon Sep 17 00:00:00 2001 From: Julien Desfossez Date: Tue, 13 Jun 2017 14:03:50 -0400 Subject: [PATCH] Fix: flush stream without packet_context MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Ensure we can flush a stream with only one packet if it does not have a packet_context or the packet_size field. Also truncate the stream to the content_size instead of the default 32kB packet size. Signed-off-by: Julien Desfossez Signed-off-by: Jérémie Galarneau --- lib/ctf-ir/stream.c | 54 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/lib/ctf-ir/stream.c b/lib/ctf-ir/stream.c index 3348eaed..cf30d09d 100644 --- a/lib/ctf-ir/stream.c +++ b/lib/ctf-ir/stream.c @@ -1463,6 +1463,7 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream) struct bt_ctf_stream_pos packet_context_pos; struct bt_ctf_trace *trace; enum bt_ctf_byte_order native_byte_order; + bool has_packet_size = false; if (!stream) { BT_LOGW_STR("Invalid parameter: stream is NULL."); @@ -1476,19 +1477,23 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream) goto end; } - if (stream->flushed_packet_count == 1) { + if (stream->packet_context) { struct bt_ctf_field *packet_size_field; + packet_size_field = bt_ctf_field_structure_get_field( + stream->packet_context, "packet_size"); + has_packet_size = (packet_size_field != NULL); + bt_put(packet_size_field); + } + + if (stream->flushed_packet_count == 1) { if (!stream->packet_context) { BT_LOGW_STR("Cannot flush a stream which has no packet context field more than once."); ret = -1; goto end; } - packet_size_field = bt_ctf_field_structure_get_field( - stream->packet_context, "packet_size"); - bt_put(packet_size_field); - if (!packet_size_field) { + if (!has_packet_size) { BT_LOGW_STR("Cannot flush a stream which has no packet context's `packet_size` field more than once."); ret = -1; goto end; @@ -1594,8 +1599,24 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream) } } + if (!has_packet_size && stream->pos.offset % 8 != 0) { + BT_LOGW("Stream's packet context field type has no `packet_size` field, " + "but current content size is not a multiple of 8 bits: " + "content-size=%" PRId64 ", " + "packet-size=%" PRIu64, + stream->pos.offset, + stream->pos.packet_size); + ret = -1; + goto end; + } + assert(stream->pos.packet_size % 8 == 0); + /* + * Remove extra padding bytes. + */ + stream->pos.packet_size = (stream->pos.offset + 7) & ~7; + if (stream->packet_context) { /* * The whole packet is serialized at this point. Make sure that, @@ -1648,13 +1669,26 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream) g_ptr_array_set_size(stream->events, 0); stream->flushed_packet_count++; stream->size += stream->pos.packet_size / CHAR_BIT; + + do { + ret = ftruncate(stream->pos.fd, stream->size); + } while (ret == -1 && errno == EINTR); + if (ret == -1) { + BT_LOGE_ERRNO("Cannot ftruncate() stream file to new size", + "size = %" PRIu64 ", name = %s", + stream->size, + stream->name ? stream->name->str : "(null)"); + } + end: /* Reset automatically-set fields. */ - reset_structure_field(stream->packet_context, "timestamp_begin"); - reset_structure_field(stream->packet_context, "timestamp_end"); - reset_structure_field(stream->packet_context, "packet_size"); - reset_structure_field(stream->packet_context, "content_size"); - reset_structure_field(stream->packet_context, "events_discarded"); + if (stream->packet_context) { + reset_structure_field(stream->packet_context, "timestamp_begin"); + reset_structure_field(stream->packet_context, "timestamp_end"); + reset_structure_field(stream->packet_context, "packet_size"); + reset_structure_field(stream->packet_context, "content_size"); + reset_structure_field(stream->packet_context, "events_discarded"); + } if (ret < 0) { /* -- 2.34.1