Bug in Stream Buffer implementation?!

Hi,

i noticed a deadlock if i send a buffer, which is bigger than the stream buffer… Here a description:

  • created a stream buffer with 256 byte size
  • send a buffer with size 419 Byte (>256) to that stream buffer (empty at his point)

There is a comment which says:

/* In the case of the stream buffer, not being able to completely write the message in the buffer
 * is an acceptable scenario, but it has to be dealt with properly */
if( xRequiredSpace > pxStreamBuffer->xLength )
{
	/* Not enough buffer space. We will attempt to write as much as we can in this run
	 * so that the caller can send the remaining in subsequent calls. We avoid a deadlock by
	 * offering the possibility to take the 'else' branch in the  'if( xSpace < xRequiredSpace )'
	 * condition inside the following do..while loop */
	xRequiredSpace = pxStreamBuffer->xLength;

	/* TODO FIXME: Is there a check we should do with the xTriggerLevelBytes value ? */

	/* With the adjustment to 'xRequiredSpace', the deadlock is avoided, thus it's now feasible. */
	xIsFeasible = pdTRUE;
}

But a little bit later this if( xSpace < xRequiredSpace ) dont get to the else state because xSpace is 256 and xRequiredSpace is 257.
The value of xRequiredSpace seems to be correct, because pxStreamBuffer->xLength was set to xBufferSizeBytes+1 in the create function with this comment:

/* A stream buffer requires a StreamBuffer_t structure and a buffer.
	 * Both are allocated in a single call to pvPortMalloc().  The
	 * StreamBuffer_t structure is placed at the start of the allocated memory
	 * and the buffer follows immediately after.  The requested size is
	 * incremented so the free space is returned as the user would expect -
	 * this is a quirk of the implementation that means otherwise the free
	 * space would be reported as one byte smaller than would be logically
	 * expected. */
	xBufferSizeBytes++;
	pucAllocatedMemory = ( uint8_t * ) pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) ); /*lint !e9079 malloc() only returns void*. */

Is this a bug or did I something wrong?!

Regards
Andy

EDIT:
Version: FreeRTOS 10.4.1

I’m trying to find this in the latest version here https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/V10.4.2/stream_buffer.c - can you please post a link to the line in that file. You can click the line number on that URL to get a link to the line.

Mhh looks like there was change from 10.4.1 to 10.4.2… Maybe also the fix?! I will check this on Monday…

Here the line in version 10.4.1

Here the line in version 10.4.2

Ok just verified that the bug was fixed in the new version 10.4.2! No deadlock happens anymore, but i still see a problem:

The function return with the bytes written to the stream (in my case 256). But I have a timeout of portMAX_DELAY and dont expect, that the function will return, until all data (>256) was written to the stream…

What do you think?!

Regards,
Andy

EDIT:
Something else: calling the send function with a lenght of 0 result in an assertion at:

I think it should be just return 0…

any update for that issue?!

I think what you are reporting is the expected behaviour for a stream. It is equivalent to reading a TCP stream - the standard semantics for a TCP recv() function is to return as much data as is available, because in a stream there is no beginning and end of the data.

Based on the stream buffer documentation, I also expected that it would block until the trigger level number of bytes was received before returning. I was hoping to leverage that behavior for my particular use case to make the processing of received data most efficient. Would it be worthwhile to add the blocking behavior as an option?

Only after reading through the documentation several times did I find the caveat that the read will only block if the stream buffer is completely empty:

If a non zero block time is specified when a task uses xStreamBufferReceive() to read from a stream buffer that happens to be empty the task will be placed into the Blocked state (so it is not consuming any CPU time and other tasks can run)…

If anything on this page https://www.freertos.org/xStreamBufferReceive.html is not clear then please let us know and we will update it.