-
Notifications
You must be signed in to change notification settings - Fork 50
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
Implement smart pointers and signals2 tracking #90
base: noetic-devel
Are you sure you want to change the base?
Conversation
…f a raw ptr, implemented it in an example to verify it works as expected
Hello @yassiezar
But, is that conceptually right? I would say it isn't. I would like to clarify the use case you mentioned that requires bringing the client behavior pointer It seems that the ideal approach (and the way SMACC is implemented) is just the opposite, is to have client behaviors that utilize client references and their public functions to interact with them. This approach ensures that the code is executed during a safe period where we can guarantee the validity of client behaviors. Using client references should not be in general a problem since their lifetime is the whole application. Client behaviors signal callbacks are disconnected before they are disposed in memory so no error should happen. |
Hey @pabloinigoblasco. I understand your point that it shouldn't be possible for callbacks to trigger while states transition, but my investigations make me believe otherwise (see my last comments on #86 where I post a couple of examples showing member variables seemingly being deallocated while a callback is active).
This is true in principle. However, you have to remember that the pointer variables pointing to the clients can go out of scope and become invalid, even while the clients themselves are perfectly valid. This is the underlying problem.
Could you point me to the code where this happens? When I look at this, I see that client behaviours are deallocated and destroyed before the slots are disconnected from the signals. Does this not mean that the callbacks can still be triggered after a transition has been triggered? This seems to be the case here and would explain segfaults from referencing out-of-scope memory The idea I'm exploring in this PR is to use I think how tracking works is that the |
I didnt notice the updates of that thread. I have to read it thoroughly, I only had a quick read. My primary goal is to determine if the issue at hand is a bug or if you are utilizing SMACC in a manner that is prohibited by design. Nonetheless. I read in that bug the following:
That is correct by design. During the transition the state variables and client behavior variables are invalid.
When states and client behaviors are being disposed internal variables become invalid. Totally agree with that: "we are in the process of removing the object". What is that callback? is that using SmaccSignals properly?
Signals must be disconnected before deallocating client behaviors. If that is not like that in the code, there is a bug we have to fix. I will have a look to that now. |
That is the heart of the issue at hand: during transitions, client behaviour callbacks are still being run. So to answer your question, the object trying to use the client behaviour internals is the client behaviour itself! When we meet later today, I might be able to explain it more clearly
This is indeed where I think the issue may lie, but I'm not sure. When I tried to change the deallocation and disconnection ordering, I ran into heap overflows...I stopped experimenting after I made my system unresponsive the 3rd time :) |
I have been having a look to the code, it is right there is a race condition for multithreaded application that could cause a callback on a destroyed object. Hence, that is a bug that it is being shown in your application. Disconnection of callbacks for life-time objects must be (by design) just before they are disposed. This is the first solution I propose: |
This is an experimental branch to solve some of the issues we've been facing, described in #57 and #86
Basically, I've added the ability to gain access to clients from CBs as
std::weak_ptr
s rather than raw pointers. Since they were saved asstd::shared_ptr
s already within the state machine, it was a pretty straight-forward change.The main change is using
boost::signals2
tracking facility to automatically monitor and control a slot's lifetime based on when the owning CB goes out of scope. Early tests show that this might prevents the issue we've been facing where member variables are being access from a CB callback after the callback has been deallocated upon state transitions.Both these changes have been integrated in a small part within the
sm_ferrari
example's CB if you wanted to see the intended usageThis is very much WIP and a lot needs to be refined. Opening up this PR for visibility and comments
┆Issue is synchronized with this Jira Task by Unito