-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Trap earlier when a Thread instance is re-used #3862
Conversation
/morph test |
rtos/Thread.h
Outdated
@@ -347,6 +347,7 @@ class Thread { | |||
bool _dynamic_stack; | |||
Semaphore _join_sem; | |||
Mutex _mutex; | |||
bool _finished; |
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.
Random thought: Should we be ifdeffing these variables out or something for non-debug builds? Otherwise they are just wasting space.
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.
Na, its just one byte.
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.
I needed to update the PR anyway so I re-ordered this so the size stays the same 😲.
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.
This looks reasonable if we only want a thread to be startable once 👍
Result: FAILUREYour command has finished executing! Here's what you wrote!
OutputTest failed! |
507ac38
to
5d3ce1a
Compare
/morph test |
Result: FAILUREYour command has finished executing! Here's what you wrote!
OutputTest failed! |
/morph test |
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.
Could you update the documentation to reflect these changes and precise that it is not allowed to start a terminated thread ?
It is not indicated in the documentation and without this precision it is easy to guess that it is possible to reuse a terminated thread.
The API is also inconsistent because there is no way to differentiate a thread not started from a thread terminated.
rtos::Thread t;
assert(t.get_state() == Thread::Deleted);
t.start(...)
assert(t.get_state() != Thread::Deleted);
t.join(); // || t.terminate()
assert(t.get_state() == Thread::Deleted);
As a result it is impossible to start a Thread safely outside from its declaration site:
bool exec_on_thread(Thread& t) {
// might trap ... no way to avoid it by testing the state
t.start(....);
}
Last point, is it necessary to trap. Thread::start
was introduced to catch failure at user level and now an assertion for a non testable condition is introduced, I'm not sure to understand the logic.
I believe for the second run one ARCH_PRO and one HEXIWEAR had been knocked offline as the issue persisted in other CI runs. I have reset them so hopefully the same problem won't affect this run. |
Result: SUCCESSYour command has finished executing! Here's what you wrote!
OutputAll builds and test passed! |
I agree with @pan- that the documentation for the class should be updated to reflect this. It should be mentioned within the start() function documentation (that it cannot be restarted even if the thread has been terminated), and possibly in the overview of the class above the definition of the class as well. |
ea46471
to
f985a47
Compare
Since start returns an error code currently I updated this PR return an error rather than asserting. I also added a way to distinguish a thread that hasn't been started from a thread that has terminated. |
/morph test |
Result: FAILUREYour command has finished executing! Here's what you wrote!
OutputTest failed! |
@pan- Please review again |
@0xc0170 Thanks to @c1728p9 the API is now consistent but the behavior (threads can be only started once) is still not documented. I also wonder if it wouldn't be a good thing to enforce that instances have well defined and unique identity by forbidding copy constructor and copy assignment operator. |
@c1728p9 My bad, I missed that line 😞 . |
/morph test |
rtos/Thread.h
Outdated
@@ -197,6 +197,7 @@ class Thread { | |||
/** Starts a thread executing the specified function. | |||
@param task function to be executed by this thread. | |||
@return status code that indicates the execution status of the function. | |||
@note a thread can only be stared once |
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.
Should be "started once" and not "stared once".
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.
Thanks for catching this @tim-nordell-nimbelink
Calling Thread::start multiple times leads to undefined behavior since the Thread class was not designed to handle being restarted. Return an error code if Thread::start is called a second time to prevent this behavior.
If a thread hasn't been started return Inactive as the status when Thread::get_state() is called.
Make the copy constructor and assignment operator private to prevent them from being used.
f985a47
to
ab4da40
Compare
/morph test |
@pan- I make the copy constructor and assignment operator private. |
Result: FAILUREYour command has finished executing! Here's what you wrote!
|
Result: SUCCESSYour command has finished executing! Here's what you wrote!
OutputAll builds and test passed! |
Calling Thread::start multiple times leads to undefined behavior since the Thread class was not designed to handle this. Add an assert to trap immediately if Thread::start is called a second time to prevent this behavior.