Skip to content

Commit 7954334

Browse files
committed
Fix a lock-order inversion between SyncUser and SyncManager
1 parent a912119 commit 7954334

File tree

4 files changed

+23
-27
lines changed

4 files changed

+23
-27
lines changed

src/realm/object-store/sync/sync_manager.cpp

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -417,39 +417,36 @@ std::shared_ptr<SyncUser> SyncManager::get_current_user() const
417417
return cur_user_ident ? get_user_for_identity(*cur_user_ident) : nullptr;
418418
}
419419

420-
void SyncManager::log_out_user(const std::string& user_id)
420+
void SyncManager::log_out_user(const SyncUser& user)
421421
{
422422
util::CheckedLockGuard lock(m_user_mutex);
423423

424424
// Move this user to the end of the vector
425-
if (m_users.size() > 1) {
426-
auto it = std::find_if(m_users.begin(), m_users.end(), [user_id](const auto& user) {
427-
return user->identity() == user_id;
428-
});
425+
auto user_pos = std::partition(m_users.begin(), m_users.end(), [&](auto& u) {
426+
return u.get() != &user;
427+
});
429428

430-
if (it != m_users.end())
431-
std::rotate(it, it + 1, m_users.end());
432-
}
429+
auto active_user = std::find_if(m_users.begin(), user_pos, [](auto& u) {
430+
return u->state() == SyncUser::State::LoggedIn;
431+
});
433432

434433
util::CheckedLockGuard fs_lock(m_file_system_mutex);
435-
bool was_active = (m_current_user && m_current_user->identity() == user_id) ||
436-
(m_metadata_manager && m_metadata_manager->get_current_user_identity() == user_id);
434+
bool was_active = m_current_user.get() == &user ||
435+
(m_metadata_manager && m_metadata_manager->get_current_user_identity() == user.identity());
437436
if (!was_active)
438437
return;
439438

440439
// Set the current active user to the next logged in user, or null if none
441-
for (auto& user : m_users) {
442-
if (user->state() == SyncUser::State::LoggedIn) {
443-
if (m_metadata_manager)
444-
m_metadata_manager->set_current_user_identity(user->identity());
445-
m_current_user = user;
446-
return;
447-
}
440+
if (active_user != user_pos) {
441+
m_current_user = *active_user;
442+
if (m_metadata_manager)
443+
m_metadata_manager->set_current_user_identity((*active_user)->identity());
444+
}
445+
else {
446+
m_current_user = nullptr;
447+
if (m_metadata_manager)
448+
m_metadata_manager->set_current_user_identity("");
448449
}
449-
450-
if (m_metadata_manager)
451-
m_metadata_manager->set_current_user_identity("");
452-
m_current_user = nullptr;
453450
}
454451

455452
void SyncManager::set_current_user(const std::string& user_id)

src/realm/object-store/sync/sync_manager.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ class SyncManager : public std::enable_shared_from_this<SyncManager> {
193193
std::shared_ptr<SyncUser> get_current_user() const REQUIRES(!m_user_mutex, !m_file_system_mutex);
194194

195195
// Log out a given user
196-
void log_out_user(const std::string& user_id) REQUIRES(!m_user_mutex, !m_file_system_mutex);
196+
void log_out_user(const SyncUser& user) REQUIRES(!m_user_mutex, !m_file_system_mutex);
197197

198198
// Sets the currently active user.
199199
void set_current_user(const std::string& user_id) REQUIRES(!m_user_mutex, !m_file_system_mutex);

src/realm/object-store/sync/sync_user.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ void SyncUser::log_out()
358358
m_sessions.clear();
359359
}
360360

361-
sync_manager_shared->log_out_user(m_identity);
361+
sync_manager_shared->log_out_user(*this);
362362
emit_change_to_subscribers(*this);
363363
}
364364

test/object-store/sync/app.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -344,13 +344,12 @@ TEST_CASE("app: login_with_credentials integration", "[sync][app][user][baas]")
344344
int subscribe_processed = 0;
345345
auto token = app->subscribe([&subscribe_processed](auto& app) {
346346
if (!subscribe_processed) {
347-
subscribe_processed++;
348-
REQUIRE(static_cast<bool>(app.current_user()));
347+
REQUIRE(app.current_user());
349348
}
350349
else {
351-
subscribe_processed++;
352-
REQUIRE(!static_cast<bool>(app.current_user()));
350+
REQUIRE_FALSE(app.current_user());
353351
}
352+
subscribe_processed++;
354353
});
355354

356355
auto user = log_in(app);

0 commit comments

Comments
 (0)