Skip to content
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

Fix a deadlock with simultaneous sync and nonsync commit notifications while tearing down RealmCoordinator #5948

Merged
merged 2 commits into from
Oct 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* <How do the end-user experience this issue? what was the impact?> ([#????](https://github.com/realm/realm-core/issues/????), since v?.?.?)
* Calling `SectionedResults::reset_section_callback()` on a `SectionedResults` which had been evaluated would result in an assertion failure the next time the sections are evaluated ([PR #5965](https://github.com/realm/realm-core/pull/5965), since v12.10.0).
* Opening an unencrypted file with an encryption key would sometimes report a misleading error message that indicated that the problem was something other than a decryption failure ([PR #5915](https://github.com/realm/realm-core/pull/5915), since 0.86.1).
* Fix a rare deadlock which could occur when closing a synchronized Realm immediately after committing a write transaction when the sync worker thread has also just finished processing a changeset from the server ([PR #5948](https://github.com/realm/realm-core/pull/5948)).

### Breaking changes
* Websocket errors caused by the client sending a websocket message that is too large (i.e. greater than 16MB) now get reported as a `ProtocolError::limits_exceeded` error with a `ClientReset` requested by the server ([#5209](https://github.com/realm/realm-core/issues/5209)).
Expand Down
10 changes: 6 additions & 4 deletions src/realm/object-store/sync/sync_session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -785,11 +785,13 @@ void SyncSession::create_sync_session()

// Configure the sync transaction callback.
auto wrapped_callback = [weak_self](VersionID old_version, VersionID new_version) {
std::function<TransactionCallback> callback;
if (auto self = weak_self.lock()) {
util::CheckedLockGuard l(self->m_state_mutex);
if (self->m_sync_transact_callback) {
self->m_sync_transact_callback(old_version, new_version);
}
callback = self->m_sync_transact_callback;
}
if (callback) {
callback(old_version, new_version);
}
};
m_session->set_sync_transact_callback(std::move(wrapped_callback));
Expand Down Expand Up @@ -845,7 +847,7 @@ void SyncSession::create_sync_session()
});
}

void SyncSession::set_sync_transact_callback(util::UniqueFunction<sync::Session::SyncTransactCallback> callback)
void SyncSession::set_sync_transact_callback(std::function<sync::Session::SyncTransactCallback>&& callback)
{
util::CheckedLockGuard l(m_state_mutex);
m_sync_transact_callback = std::move(callback);
Expand Down
7 changes: 3 additions & 4 deletions src/realm/object-store/sync/sync_session.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,7 @@ class SyncSession : public std::enable_shared_from_this<SyncSession> {
class Internal {
friend class _impl::RealmCoordinator;

static void set_sync_transact_callback(SyncSession& session,
util::UniqueFunction<TransactionCallback> callback)
static void set_sync_transact_callback(SyncSession& session, std::function<TransactionCallback>&& callback)
{
session.set_sync_transact_callback(std::move(callback));
}
Expand Down Expand Up @@ -346,7 +345,7 @@ class SyncSession : public std::enable_shared_from_this<SyncSession> {
void handle_progress_update(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
void handle_new_flx_sync_query(int64_t version);

void set_sync_transact_callback(util::UniqueFunction<TransactionCallback>) REQUIRES(!m_state_mutex);
void set_sync_transact_callback(std::function<TransactionCallback>&&) REQUIRES(!m_state_mutex);
void nonsync_transact_notify(VersionID::version_type) REQUIRES(!m_state_mutex);

void create_sync_session() REQUIRES(m_state_mutex, !m_config_mutex);
Expand All @@ -365,7 +364,7 @@ class SyncSession : public std::enable_shared_from_this<SyncSession> {

util::Future<std::string> send_test_command(std::string body) REQUIRES(!m_state_mutex);

util::UniqueFunction<TransactionCallback> m_sync_transact_callback GUARDED_BY(m_state_mutex);
std::function<TransactionCallback> m_sync_transact_callback GUARDED_BY(m_state_mutex);

template <typename Field>
auto config(Field f) REQUIRES(!m_config_mutex)
Expand Down