-
Notifications
You must be signed in to change notification settings - Fork 168
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
Fixed double delete in CAPITimer and add documentation for platform networking CAPI integration #6994
Conversation
Pull Request Test Coverage Report for Build michael.wilkersonbarker_855
💛 - Coveralls |
d672cd4
to
f56d770
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.
I tested this branch & it fixed the double delete issue 👍 left some minor comment
src/realm.h
Outdated
RLM_API void realm_sync_socket_websocket_connected(realm_websocket_observer_t* realm_websocket_observer, | ||
const char* protocol); | ||
|
||
/** | ||
* To be called when an error occurs - the actual error value with be provided when the websocket_closed |
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.
* To be called when an error occurs - the actual error value with be provided when the websocket_closed | |
* To be called when an error occurs - the actual error value will be provided when the websocket_closed |
@@ -4069,17 +4088,79 @@ RLM_API realm_sync_socket_t* realm_sync_socket_new( | |||
realm_sync_socket_websocket_async_write_func_t websocket_write_func, | |||
realm_sync_socket_websocket_free_func_t websocket_free_func); | |||
|
|||
RLM_API void realm_sync_socket_callback_complete(realm_sync_socket_callback_t* realm_callback, realm_errno_e status, |
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 used to be called after a websocket_async_write_func
to indicate error/complete via the callback provided in
Line 383 in f56d770
realm_sync_socket_callback_t* realm_callback); |
we can use alternatively
realm_sync_socket_post_complete
...
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.
Oh, right - I forgot about that callback. I'll create a new function realm_sync_socket_write_complete()
so it's obvious when it should be called (even though it does the same as post_complete
)
|
||
// These values were originally provided to the socket_provider instance by the CAPI | ||
// implementation when it was created | ||
realm_userdata_t m_userdata = nullptr; |
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 don't think this is initialized via the ctor, it is also passed to
realm-core/src/realm/object-store/c_api/socket_provider.cpp
Lines 29 to 30 in f56d770
m_timer_cancel(m_userdata, m_timer); | |
m_timer_free(m_userdata, m_timer); |
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 is an overlook, so it should be.
* @param reason a string describing details about the error that occurred or empty string if no error. | ||
* NOTE: This function must be called by the event loop execution thread. | ||
*/ | ||
RLM_API void realm_sync_socket_timer_complete(realm_sync_socket_callback_t* timer_handler, realm_errno_e status, |
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.
aren't these two new api calls leaking the callback if realm_sync_socket_post_complete is never called?
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.
These two callbacks are meant to be used with the CAPITimer, which will release the callback handler when the timer is destroyed.
Do you think it would be better to not call realm_release(m_handler)
in the destructor and rely on the call to timer_complete/timer_canceled to delete m_handler
?
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.
Maybe I should rethink the callback handler a bit differently so the callback isn't called multiple times...
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.
Yeah, that's an option. I just saw you kept the release in dtor, so there is no leak. But, how is double free gone? (can't the callback be invoked followed by release, and then when the timer is gone there is a new release?)
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.
The double free is gone, since you're supposed to use the timer_complete()
or timer_canceled()
fcns, which doesn't call release, so there's only one release when the timer is destroyed (if the CAPI is implemented properly), however, the callback could be called multiple times depending on how the timer is implemented. (cancel is always called in the destructor to make sure the timer is stopped)
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.
but post
calls release.. That was the initial issue
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.
But you're not supposed to use post (or write_complete) with the timer handler, which are different objects from the callback handlers provided to the post or async_write functions.
* @param timer_handler the timer callback handler that was provided when the timer was created. | ||
* NOTE: This function must be called by the event loop execution thread. | ||
*/ | ||
RLM_API void realm_sync_socket_timer_canceled(realm_sync_socket_callback_t* timer_handler); |
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.
we should test the new api calls
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.
we could even recreate the initial issue using TestSyncTimer
in c_api.cpp
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.
Looks good. I would add a few more tests though.
Created RCORE-1793/ #6998 to add more tests as a separate task |
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.
Tested again using the new realm_sync_socket_write_complete
looks good!
What, How & Why?
There was a double delete occurring of the callback handler when a CAPITimer object was destroyed in the CAPI implementation after having called
realm_sync_socket_callback_complete()
to report timer status. Broke up therealm_sync_socket_callback_complete()
to use 4 separate functions instead:realm_sync_socket_timer_complete()
- to be used when a timer expires or an error occursrealm_sync_socket_timer_canceled()
- to be used when a timer has been canceledrealm_sync_socket_post_complete()
- to be used when a callback handler added usingpost()
is ready to runrealm_sync_socket_write_complete()
- to be used when a websocket write operation has completedThe CAPITimer's callback handler will only be destroyed when the CAPITimer object is destroyed.
Added documentation to the Platform Networking functions in
realm.h
to describe their purpose to help with future custom platform networking implementations.FIxes #6993
☑️ ToDos
[ ] 🚦 Tests (or not relevant)[ ] C-API, if public C++ API changed.