-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Fix semaphores in IDF & std::string assert #2728
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
9be59b9
Fix semaphores in IDF & std::string assert
h2zero 2d5e739
Merge pull request #1 from espressif/master
h2zero 9919451
Restored m_owner position in wait() as requested
h2zero 8fd7f05
Reapply assert fix and move setting m_owner in ::give()
h2zero File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting the owner before we take the semaphore seems like maybe it can lead to incorrect behaviour. Think about this sequence of events:
s->wait("task_a")
. m_owner is set to "task_a", and then waiting for the semaphore succeeds because noone was holding it.s->wait("task_b")
. m_owner is set to "task_b" but then Task B is blocked in xSemaphoreWait() because Task A is still holding the semaphore.Now we have a situation where Task A is holding the semaphore, but the owner field indicates Task B is holding it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, hadn't really thought about it as the way the BLE library currently works (on the client side anyway) there is multiple semaphores used and only one task actually takes each of them. Also, as this was a mutex before, the semaphore is usually taken already before we call the wait function to block the task and wait for the callback to give the semaphore back, at which time it sets m_owner to "<N/A>" anyway.
The reason for this change though is I've encountered many instances of on assert error when giving the semaphore from the callback as both cores sometimes try to write to m_owner at the same time, one in the give() on core 0 and this one after we've unblocked in wait() on core 1.
Anyway, maybe a better solution would be to pin the callback task to core 1, or maybe just remove the setting of m_owner in wait() all together? I'm open to suggestions :).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the point of this
m_owner
anyway? Logging?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes as far as I can tell it’s only used for logging, but I suppose someone could call the toString() method on the semaphore to check ownership.
I’m tempted just to remove it entirely for my use, but others might find it useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@h2zero
Right, sorry I should have read the full code - I missed that wait() isn't "take", it's "take then give". Not quite what I expected...
If this is the problem then I think the best solution is to change all the m_owner assignments so they only happen when holding the semaphore, so the semaphore protects against any race condition. I think this means:
::give()
, move setting ofm_owner
up to before the semaphore is given so it's assigned while the caller still holds the semaphore.::wait()
, don't set m_owner at all. As soon as the caller in wait() gets the semaphore it gives it back, and giving a semaphore never blocks, so if you did set m_owner then it gets immediately un-set afterwards which seems like a waste of CPU cycles.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@projectgus
Yeah that’s along the line of my thinking as well. Sorry I changed the PR yesterday assuming you wanted me to revert the m_owner move and I didn’t see your reply here first. I’ll make the changes as you’ve mentioned and fix the PR again lol.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@projectgus
Made the changes, tested with my test code that would cause the assert within seconds and has been running over an hour now. Logging works fine as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! :)