From d68ea990ca38b6222ded8e97c55d466a7402ebfc Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Tue, 13 Jan 2015 19:19:30 +0100 Subject: [PATCH] sal: catch listener removal corner case This change makes sure an active but not-yet fired listener does not fire anymore if it gets removed. In this case, the listener already has an invalid index, but still needs to be copied to the delete list. This issue has not been observed in the wild, and is unlikely to have caused real problems in the past. Change-Id: I8be8a5b1d4cdc783a092b93f34f33b969894e5da --- src/core/sal/ListenerManager.cc | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/core/sal/ListenerManager.cc b/src/core/sal/ListenerManager.cc index dbe7808e..8e804c78 100644 --- a/src/core/sal/ListenerManager.cc +++ b/src/core/sal/ListenerManager.cc @@ -50,16 +50,22 @@ void ListenerManager::remove(BaseListener* li) // called onDeletion for these listeners): m_DeleteList.insert(m_DeleteList.end(), m_FireList.begin(), m_FireList.end()); - // - li != 0 -> remove single listener (if added previously) - // * Inform the listeners (call onDeletion) - // * Remove the index in the perf. buffer-list (if existing) - // * Find/remove 'li' in 'm_BufferList' + // - li != 0 -> remove single listener + // * If added / not removed before, + // -> inform the listeners (call onDeletion) + // -> Remove the index in the perf. buffer-list (if existing) + // -> Find/remove 'li' in 'm_BufferList' // * If 'li' in 'm_FireList', copy to 'm_DeleteList' - } else if (li->getLocation() != INVALID_INDEX) { // Check if li hasn't been added previously (Q&D) - li->onDeletion(); - if (li->getPerformanceBuffer() != NULL) - li->getPerformanceBuffer()->remove(li->getLocation()); - m_remove(li->getLocation()); + } else { + // has li been removed previously? + if (li->getLocation() != INVALID_INDEX) { + li->onDeletion(); + if (li->getPerformanceBuffer() != NULL) { + li->getPerformanceBuffer()->remove(li->getLocation()); + } + m_remove(li->getLocation()); + } + // if li hasn't fired yet, make sure it doesn't firelist_t::const_iterator it = std::find(m_FireList.begin(), m_FireList.end(), li); if (it != m_FireList.end()) {