Fix crash caused by race condition in xSemaphoreTake #173
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #172.
This race condition would make infinisim eventually crash with the message "Mutex released without being held" on my machine.
The function
xSemaphoreTakewaits for the semaphore to be available to take by looping + sleeping until there is an element in thepxQueue->queue. Then it locks thepxQueue->mutexand checks the queuesize again. Since the first check is not done under the mutex, some other thread could remove the element from the queue before the mutex is locked. Then the second check inxSemaphoreTakewill return false. The methodDateTimeController::CurrentDateTime()uses a semaphore as a mutex to guard calls toUpdateTime(). But it (and the other methods fromDateTimeController) do not check ifxSemaphoreTakeactually gave them the semaphore. They will try to give it back even if they failed to take it, which leads to the crash inxSemaphoreGive. The other thread in this crash was calling the watchface refresh method, which also callsCurrentDateTime().To fix the race condition, lock the mutex guarding
pxQeue->queuebefore checking the queue size and unlock before sleeping. When implemented like this,xSemaphoreTakefrom InfiniSim follows the API from FreeRTOS more closely, which waits the fullxTicksToWaitwhile InfiniSim would abort prematurely in some cases.With the assumption that
UpdateTime()will finish within some finite amount of time, this makes the methods inDateTimerControllerwork even without error handling since they have such long wait times.