From b11134e1bcc34fcc7750ebfdcd36508fb464454e Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Mon, 29 Apr 2019 09:55:57 +0900 Subject: [PATCH] Fix race condition in NotePlayHandleManager NotePlayHandleManager::acquire uses a read lock unless the pool is empty. If two threads try to acquire NotePlayHandle simultaneously when the value of s_availableIndex is 1, one thread may return null pointer. Also, the ABA problem may occur when the acquire action and the release action are done at the same time. This commit prevents this by always using the write lock when acquiring a NotePlayHandle. --- src/core/NotePlayHandle.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index 84d83bb0a78..1e6ce01c9e4 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -577,13 +577,9 @@ NotePlayHandle * NotePlayHandleManager::acquire( InstrumentTrack* instrumentTrac int midiEventChannel, NotePlayHandle::Origin origin ) { - if( s_availableIndex < 0 ) - { - s_mutex.lockForWrite(); - if( s_availableIndex < 0 ) extend( NPH_CACHE_INCREMENT ); - s_mutex.unlock(); - } - s_mutex.lockForRead(); + // TODO: use some lockless data structures + s_mutex.lockForWrite(); + if (s_availableIndex < 0) { extend(NPH_CACHE_INCREMENT); } NotePlayHandle * nph = s_available[ s_availableIndex.fetchAndAddOrdered( -1 ) ]; s_mutex.unlock();