-
Notifications
You must be signed in to change notification settings - Fork 7.9k
kernel: Add assert for init'ing pending k_work #93279
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
Conversation
Adds asserts for both k_work and k_work_delayable to prevent users from initializing work items that are currently pending. If a workqueue has e.g. 3 items pending, A, B and C, and work item B is provided to k_work_init, then the workqueue becomes corrupt and items B and C will be removed from the queue. Signed-off-by: Emil Gydesen <[email protected]>
e5b0e4d
to
5039260
Compare
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.
Pull Request Overview
Adds runtime checks to prevent initializing work items that are already pending and updates tests to zero-initialize work structures.
- Introduce
__ASSERT_NO_MSG(!k_work_is_pending(work))
ink_work_init
and its delayable variant - Include the assert header in
kernel/work.c
- Update tests to zero-initialize
struct k_work
andstruct k_work[]
to satisfy the new assertions
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
File | Description |
---|---|
tests/kernel/workq/work_queue/src/start_stop.c | Zero-initialize work and works to ensure they're not flagged pending |
kernel/work.c | Add __ASSERT_NO_MSG checks before initializing pending work items and include <zephyr/sys/__assert.h> |
Comments suppressed due to low confidence (2)
kernel/work.c:159
- [nitpick] The assertion uses __ASSERT_NO_MSG without a descriptive message. Consider adding a message to clarify the failure reason, e.g., "k_work_init: work is already pending".
__ASSERT_NO_MSG(!k_work_is_pending(work));
kernel/work.c:991
- [nitpick] The assertion uses __ASSERT_NO_MSG without a descriptive message. Consider adding a message to clarify the failure reason, e.g., "k_work_init_delayable: work is already pending".
__ASSERT_NO_MSG(!k_work_delayable_is_pending(dwork));
|
On a side note, it's pretty wild that invalidating a single work item added to the system workqueue can corrupt the entire system workqueue's queue. For example, if the system workqueue has items A, B and C, and the owner of item B either intentionally or accidentally It may also affect any other workqueue (or any slist or dlist for that matter), but the system workqueue is unique in that it's being used by a lot of subsystems and applications as well, so it's way more exposed. |
You don't have any guarantees about the value of *work = (struct k_work)Z_WORK_INITIALIZER(handler); |
Yeah, I noticed this being a problem in some of the unit tests, and setting them to In any case, it would also help prevent against re-initializing a k_work item using the @pdgendt Can you think of any other approaches to help prevent the issue I found? |
Sorry, not really, I think this is the contract users need to adhere to.
As the work items are in a single linked list, and the work struct has the pointer to the |
Yeah, I suppose you are right. The only alternative I see is a completely new API using abstract objects and allocation/deallocation functions (which still doesn't prevent I think I'll close the PR due to not being able to perform any checks on |
Adds asserts for both k_work and k_work_delayable to prevent users from initializing work items that are currently pending.
If a workqueue has e.g. 3 items pending, A, B and C, and work item B is provided to k_work_init, then the workqueue becomes corrupt and items B and C will be removed from the queue.