Fix assertion failure when a notifier is removed before it runs
This commit is contained in:
parent
eee6e55eb0
commit
8879212111
|
@ -235,13 +235,17 @@ void RealmCoordinator::pin_version(uint_fast64_t version, uint_fast32_t index)
|
||||||
}
|
}
|
||||||
else if (m_new_notifiers.empty()) {
|
else if (m_new_notifiers.empty()) {
|
||||||
// If this is the first notifier then we don't already have a read transaction
|
// If this is the first notifier then we don't already have a read transaction
|
||||||
|
REALM_ASSERT_3(m_advancer_sg->get_transact_stage(), ==, SharedGroup::transact_Ready);
|
||||||
m_advancer_sg->begin_read(versionid);
|
m_advancer_sg->begin_read(versionid);
|
||||||
}
|
}
|
||||||
else if (versionid < m_advancer_sg->get_version_of_current_transaction()) {
|
else {
|
||||||
// Ensure we're holding a readlock on the oldest version we have a
|
REALM_ASSERT_3(m_advancer_sg->get_transact_stage(), ==, SharedGroup::transact_Reading);
|
||||||
// handover object for, as handover objects don't
|
if (versionid < m_advancer_sg->get_version_of_current_transaction()) {
|
||||||
m_advancer_sg->end_read();
|
// Ensure we're holding a readlock on the oldest version we have a
|
||||||
m_advancer_sg->begin_read(versionid);
|
// handover object for, as handover objects don't
|
||||||
|
m_advancer_sg->end_read();
|
||||||
|
m_advancer_sg->begin_read(versionid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,10 +286,12 @@ void RealmCoordinator::clean_up_dead_notifiers()
|
||||||
// are no notifiers left, but don't close them entirely as opening shared
|
// are no notifiers left, but don't close them entirely as opening shared
|
||||||
// groups is expensive
|
// groups is expensive
|
||||||
if (m_notifiers.empty() && m_notifier_sg) {
|
if (m_notifiers.empty() && m_notifier_sg) {
|
||||||
|
REALM_ASSERT_3(m_notifier_sg->get_transact_stage(), ==, SharedGroup::transact_Reading);
|
||||||
m_notifier_sg->end_read();
|
m_notifier_sg->end_read();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (swap_remove(m_new_notifiers)) {
|
if (swap_remove(m_new_notifiers)) {
|
||||||
|
REALM_ASSERT_3(m_advancer_sg->get_transact_stage(), ==, SharedGroup::transact_Reading);
|
||||||
if (m_new_notifiers.empty() && m_advancer_sg) {
|
if (m_new_notifiers.empty() && m_advancer_sg) {
|
||||||
m_advancer_sg->end_read();
|
m_advancer_sg->end_read();
|
||||||
}
|
}
|
||||||
|
@ -424,7 +430,14 @@ void RealmCoordinator::run_async_notifiers()
|
||||||
IncrementalChangeInfo new_notifier_change_info(*m_advancer_sg, new_notifiers);
|
IncrementalChangeInfo new_notifier_change_info(*m_advancer_sg, new_notifiers);
|
||||||
|
|
||||||
if (!new_notifiers.empty()) {
|
if (!new_notifiers.empty()) {
|
||||||
REALM_ASSERT(m_advancer_sg->get_version_of_current_transaction() == new_notifiers.front()->version());
|
REALM_ASSERT_3(m_advancer_sg->get_transact_stage(), ==, SharedGroup::transact_Reading);
|
||||||
|
REALM_ASSERT_3(m_advancer_sg->get_version_of_current_transaction().version,
|
||||||
|
<=, new_notifiers.front()->version().version);
|
||||||
|
|
||||||
|
// The advancer SG can be at an older version than the oldest new notifier
|
||||||
|
// if a notifier was added and then removed before it ever got the chance
|
||||||
|
// to run, as we don't move the pin forward when removing dead notifiers
|
||||||
|
transaction::advance(*m_advancer_sg, nullptr, new_notifiers.front()->version());
|
||||||
|
|
||||||
// Advance each of the new notifiers to the latest version, attaching them
|
// Advance each of the new notifiers to the latest version, attaching them
|
||||||
// to the SG at their handover version. This requires a unique
|
// to the SG at their handover version. This requires a unique
|
||||||
|
@ -446,6 +459,7 @@ void RealmCoordinator::run_async_notifiers()
|
||||||
version = m_advancer_sg->get_version_of_current_transaction();
|
version = m_advancer_sg->get_version_of_current_transaction();
|
||||||
m_advancer_sg->end_read();
|
m_advancer_sg->end_read();
|
||||||
}
|
}
|
||||||
|
REALM_ASSERT_3(m_advancer_sg->get_transact_stage(), ==, SharedGroup::transact_Ready);
|
||||||
|
|
||||||
// Make a copy of the notifiers vector and then release the lock to avoid
|
// Make a copy of the notifiers vector and then release the lock to avoid
|
||||||
// blocking other threads trying to register or unregister notifiers while we run them
|
// blocking other threads trying to register or unregister notifiers while we run them
|
||||||
|
|
Loading…
Reference in New Issue