-
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
Added sync socket result enum for sync socket callback handlers in C API #7015
Conversation
Pull Request Test Coverage Report for Build michael.wilkersonbarker_904
💛 - Coveralls |
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.
LGTM 🎉 minor comments
typedef enum realm_sync_socket_callback_result { | ||
// These error values are pulled directly from realm_errno_e | ||
RLM_ERR_SYNC_SOCKET_SUCCESS = RLM_ERR_NONE, | ||
RLM_ERR_SYNC_SOCKET_OPERATION_ABORTED = RLM_ERR_OPERATION_ABORTED, |
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.
FWIW we're only using the two above.
static void realm_sync_socket_op_complete(realm_sync_socket_callback* realm_callback, realm_errno_e status, | ||
const char* reason) | ||
static void realm_sync_socket_op_complete(realm_sync_socket_callback* realm_callback, | ||
realm_sync_socket_callback_result_e result, const char* reason) | ||
{ | ||
if (realm_callback->get() != 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.
Since we moved the realm_callback
release inside this method, is there a scenario where realm_callback->get() == nullptr
? In fact, a double invocation (by error) of realm_sync_socket_op_complete
will SIGSEGV before invoking get()
since the realm_callback
pointer was previously released.
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 technically don't need it anymore - I'll remove it
@@ -15,8 +15,7 @@ struct CAPITimer : sync::SyncSocketProvider::Timer { | |||
realm_sync_socket_create_timer_func_t create_timer_func, | |||
realm_sync_socket_timer_canceled_func_t cancel_timer_func, | |||
realm_sync_socket_timer_free_func_t free_timer_func) | |||
: m_handler(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.
what prompted this change?
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 were allowing the CAPITimer to delete the handler, but really it should have been "owned" by the implementation and freed when the complete/cancelled function was called, similar to the post and write_async callbacks.
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 think the idea was that if none of the functions is called and the timer is deallocated, it then deallocates the handler too. Is that still possible?
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 have to call either realm_sync_socket_timer_canceled
or realm_sync_socket_timer_complete
which free the handler otherwise the syn client hangs indefinitely waiting for the posted timer(s) to complete https://github.com/realm/realm-core/blob/master/src/realm/sync/client.cpp#L477-L478
This is why we should not rely on the dtor to free it.
Another issue with the current approach is that the m_timer_cancel(m_userdata, m_timer)
runs asynchronously whereas realm_release(m_handler);
below runs synchronously which will delete the FunctionHandler before it gets a chance to be used inside the event loop
RLM_ERR_SYNC_SOCKET_SUCCESS = RLM_ERR_NONE, | ||
RLM_ERR_SYNC_SOCKET_OPERATION_ABORTED = RLM_ERR_OPERATION_ABORTED, | ||
RLM_ERR_SYNC_SOCKET_RUNTIME = RLM_ERR_RUNTIME, | ||
RLM_ERR_SYNC_SOCKET_OUT_OF_MEMORY = RLM_ERR_OUT_OF_MEMORY, |
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.
Are we sure we want/need users provide some of these errors? (i.e, RLM_ERR_SYNC_SOCKET_OUT_OF_MEMORY)
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.
No, but they could potentially be returned via the async write callback.
test/object-store/c_api/c_api.cpp
Outdated
}; | ||
|
||
struct TestWebSocket : realm::c_api::WrapC, WebSocketInterface { | ||
public: | ||
TestWebSocket(DefaultSocketProvider& socket_provider, realm_websocket_endpoint_t endpoint, | ||
TestWebSocket(DefaultSocketProvider* socket_provider, realm_websocket_endpoint_t endpoint, |
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.
not sure why we want this change
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 - reverted
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.
LGTM - make sure to fix the leak 👍
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 it again, CI is happy 👍
The three failures in the following test run were due to unrelated timeouts during the test. Created issue 7071 to investigate these failures: |
@@ -116,7 +107,7 @@ struct CAPIWebSocket : sync::WebSocketInterface { | |||
} | |||
|
|||
/// Destroys the web socket instance. | |||
~CAPIWebSocket() | |||
virtual ~CAPIWebSocket() |
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.
doesn't need to be virtual
src/realm.h
Outdated
@@ -355,35 +355,70 @@ typedef struct realm_websocket_endpoint { | |||
bool is_ssl; // true if SSL should be used | |||
} realm_websocket_endpoint_t; | |||
|
|||
// The following definitions are for internal structures and pointers used |
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.
It seems the SDKs use them too. I am not a big fan splitting it this way, but I don't have a strong opinion either. People directly using this API can have their say.
What, How & Why?
Added the
realm_sync_socket_callback_result_e
enum to be used for passing to the callback handler functions in the C API Platform Networking interface. This contains a subset of therealm_errno_e
enum values that can be more easily used with this interface and simplifies this part of the interface, since it narrows down the set of possible errors that should be provided to the callback handlers.NOTE: Additional errors were included that were believed to be applicable from the Platform Networking point of view, if they can be detected by the implementation. For the most part, the primary values used will be
RLM_ERR_SYNC_SOCKET_SUCCESS
orRLM_ERR_SYNC_SOCKET_OPERATION_ABORTED
.Fixes #7014
☑️ ToDos