Jan Kiszka wrote:
> Gilles Chanteperdrix wrote:
>> Jan Kiszka wrote:
>>> Christoph Permes wrote:
>>>> Hi,
>>>>
>>>> I've created a patch that provides a workaround for the segmentation
>>>> fault:
>>>>
>>>> --- a/src/rtdk/rt_print.c 2009-05-21 16:34:54.000000000 +0200
>>>> +++ b/src/rtdk/rt_print.c 2009-09-04 10:09:19.000000000 +0200
>>>> @@ -40,6 +40,7 @@
>>>> struct entry_head {
>>>> FILE *dest;
>>>> uint32_t seq_no;
>>>> + uint32_t len;
>>>> char text[1];
>>>> } __attribute__((packed));
>>>>
>>>> @@ -113,6 +114,7 @@
>>>> /* Write out empty entry */
>>>> head = buffer->ring + write_pos;
>>>> head->seq_no = __seq_no;
>>>> + head->len = 0;
>>>> head->text[0] = 0;
>>>>
>>>> /* Forward to the ring buffer start */
>>>> @@ -146,6 +148,7 @@
>>>> /* If we were able to write some text, finalise the entry */
>>>> if (len > 0) {
>>>> head->seq_no = ++__seq_no;
>>>> + head->len = len;
>>>> head->dest = stream;
>>>>
>>>> /* Move forward by text and head length */
>>>> @@ -158,6 +161,7 @@
>>>> /* An empty entry marks the wrap-around */
>>>> head = buffer->ring + write_pos;
>>>> head->seq_no = __seq_no;
>>>> + head->len = 0;
>>>> head->text[0] = 0;
>>>>
>>>> write_pos = 0;
>>>> @@ -373,7 +377,7 @@
>>>>
>>>> read_pos = buffer->read_pos;
>>>> head = buffer->ring + read_pos;
>>>> - len = strlen(head->text);
>>>> + len = head->len;
>>>>
>>>> if (len) {
>>>> /* Print out non-empty entry and proceed */
>>>>
>>>> With this patch I get no segfaults anymore, but of course it would be
>>>> interesting why parts of the ring buffer are overwritten with null
>>>> characters.
>>>>
>>> Frankly, I'm suspecting some issue in your application here - at least
>>> as long as you do not have some broken-out test case for us...
>> Would not it be possible to mprotect the rtdk buffer when it is not used
>> in order to catch any write to it outside of rtdk functions?
>>
>
> Hmm, good idea, should work. Once set up, only rt_vsnprintf requires
> write access to the ring.
Ok. Here it comes. Note however that calling rt_printf with this patch
will cause the caller to switch to secondary mode, but that is OK for
debugging. Also note that I only compile-tested the patch.
--
Gilles
diff --git a/src/rtdk/rt_print.c b/src/rtdk/rt_print.c
index 10285c0..5e7cda6 100644
--- a/src/rtdk/rt_print.c
+++ b/src/rtdk/rt_print.c
@@ -101,6 +101,7 @@ int rt_vfprintf(FILE *stream, const char *format, va_list args)
read_pos = buffer->read_pos;
xnarch_read_memory_barrier();
+ mprotect(buffer->ring, buffer->size, PROT_READ | PROT_WRITE);
/* Is our write limit the end of the ring buffer? */
if (write_pos >= read_pos) {
/* Keep a savety margin to the end for at least an empty entry */
@@ -165,6 +166,7 @@ int rt_vfprintf(FILE *stream, const char *format, va_list args)
/* All entry data must be written before we can update write_pos */
xnarch_write_memory_barrier();
+ mprotect(buffer->ring, buffer->size, PROT_READ);
buffer->write_pos = write_pos;
@@ -221,6 +223,7 @@ int rt_print_init(size_t buffer_size, const char *buffer_name)
size = __default_buffer_size;
else if (size < RT_PRINT_LINE_BREAK)
return EINVAL;
+ size = (size + getpagesize() - 1) & ~(getpagesize() - 1);
if (buffer) {
/* Only set name if buffer size is unchanged or default */
@@ -235,12 +238,11 @@ int rt_print_init(size_t buffer_size, const char *buffer_name)
if (!buffer)
return ENOMEM;
- buffer->ring = malloc(size);
+ buffer->ring = mmap(NULL, size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (!buffer->ring) {
free(buffer);
return ENOMEM;
}
- memset(buffer->ring, 0, size);
buffer->read_pos = 0;
buffer->write_pos = 0;
_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help