Closed cmorganBE closed 1 year ago
HI @cmorganBE , Thank you for reporting the bug.
Can you please help me know when you are calling xTaskCreateStatic from the app_main() are you passing pxTaskBuffer as NULL? That is why hitting the above issue?
From the details mentioned here, If neither puxStackBuffer or pxTaskBuffer are NULL then the task will be created, and the task's handle is returned. If either puxStackBuffer or pxTaskBuffer is NULL then the task will not be created and NULL will be returned.
Can you please give more details on how you are calling xTaskCreateStatic.
@moninom1 let me modify the demo app to use the functions we are using and confirm it reproduces. If so I can push that to a fork to show an example, and if not it could help me figure out if its a usage error on our side. The same code is running on target hardware though... should have something by tomorrow
@cmorganBE Hey, looking at your stack trace it looks like you're hitting an interrupt while creating that new task?
The first line of tasks.c:xTaskCreateStatic() is taskENTER_CRITICAL
. This is used to stop interrupts from coming through:
static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
{
/* Ensure interrupts don't access the task lists while the lists are being
* updated. */
taskENTER_CRITICAL();
taskENTER_CRITICAL()
then gets mapped to vPortEnterCritical
void vPortEnterCritical( void )
{
if( uxCriticalNesting == 0 )
{
vPortDisableInterrupts();
}
uxCriticalNesting++;
}
But looking at your posted stack trace it looks like your call to prvAddNewTaskToReadyList()
is instead triggering a call to vPortYield()
? Where performing this before getting to execute the code in prvAddNewTaskToReadyList()
that would set pxCurrentTCB
to be the new TCB could be the root of your problem
static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
{
/* Ensure interrupts don't access the task lists while the lists are being
* updated. */
taskENTER_CRITICAL();
{
uxCurrentNumberOfTasks++;
if( pxCurrentTCB == NULL )
{
/* There are no other tasks, or all the other tasks are in
* the suspended state - make this the current task. */
pxCurrentTCB = pxNewTCB;
Can you potentially step through your existing code in a debugger and just ensure that the correct order of functions is occuring?
@Skptak note that I'm using the posix gcc port here. I'm hitting #826 when building here but once I'm able to build I'll adjust the demo to attempt to reproduce.
Looking through our code here I think this may be related to the system state being reused. We are using catch2 and each test case will create all threads and then they'd be shut down at the end of the test case. However, all of this is done from within a single app_main() that we call from a task we create from our simulation executable's main() like:
int main(int argc, char *argv[])
{
COMMAND_LINE_ARGS command_line_args = {.argc = argc, .argv = argv};
/* Do not include trace code when performing a code coverage analysis. */
#if ( projCOVERAGE_TEST != 1 )
{
/* Initialise the trace recorder. Use of the trace recorder is optional.
* See http://www.FreeRTOS.org/trace for more information. */
vTraceEnable( TRC_START );
/* Start the trace recording - the recording is written to a file if
* configASSERT() is called. */
printf( "\r\nTrace started.\r\nThe trace will be dumped to disk if a call to configASSERT() fails.\r\n" );
#if ( TRACE_ON_ENTER == 1 )
printf( "\r\nThe trace will be dumped to disk if Enter is hit.\r\n" );
#endif
traceSTART();
}
#endif /* if ( projCOVERAGE_TEST != 1 ) */
TaskHandle_t taskHandle;
xTaskCreate( app_main_wrapper, /* The function that implements the task. */
"app_main_wrapper", /* The text name assigned to the task - for debug only as it is not >
configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
&command_line_args, /* The parameter passed to the task - not used in this simple case. */
mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */
&taskHandle ); /* The task handle is not required, so NULL is passed. */
// Start the real time scheduler.
vTaskStartScheduler();
printf("vTaskStartScheduler() returned\n");
printf("deleting taskHandle\n");
vTaskDelete(taskHandle);
printf("exiting main\n");
return 0;
}
The failure occurs on the second test case that is run, the first run of xTaskCreateStatic() of the object is successful, but the next instance of the same object for the second test case has the failure as seen above.
I guess on that topic, @Skptak, how should we be cleaning up all of the threads so we can re-run initialization from inside of the same process and start with a clean slate? There are actually a fair number of valgrind leaks due to threads that are ended (by calling vTaskDelete on themselves), but seemed to be stuck in a kind of cancelled state.
Is there a good location for a test for that? I'd be interested in writing some tests for the posix implementation that run under CI/CD and valgrind to replicate the issue so it can be investigated. We ended up having to use suppressions for the various leaks.
As per the guidance when opening a git issue - please discuss this on the forums before discussing here, and open a bug report if that is the conclusion of the forum discussion - thanks.
Describe the bug prvAddNewTaskToReadyList() expects a valid pxCurrentTCB but this is null.
Target
Host
To Reproduce Call xTaskCreateStatic() from app_main().
Expected behavior xTaskCreateStatic() would work.