From b9503a8c7094dd175cb8261a56832343a4451f61 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Wed, 8 May 2019 15:12:17 +0900 Subject: [PATCH] Fix race conditions in NotePlayHandleManager (#4966) 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 will try to read s_available[-1]. If the acquire action and the release action are done at the same time, NotePlayHandleManager::acquire may try to read data before NotePlayHandleManager::release actually writes. This commit prevents them 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();