From e3029a5e174670875af9b5ccdc1fca94e682a82c Mon Sep 17 00:00:00 2001 From: Thomas Mellenthin Date: Tue, 20 Apr 2021 11:08:02 +0200 Subject: [PATCH] =?UTF-8?q?Fix=20"Semaphore=20object=20deallocated=20while?= =?UTF-8?q?=20in=20use"-crash=20=F0=9F=A4=9E=20(#4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix "Semaphore object deallocated while in use"-crash 🤞 * Fix the initial value as well (this has no practical impact, I just want to avoid having DispatchSemaphore(value:1) anywhere in the code) --- Sources/CombineLongPolling/LongPollingPublisher.swift | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Sources/CombineLongPolling/LongPollingPublisher.swift b/Sources/CombineLongPolling/LongPollingPublisher.swift index 42f026e..99fd0fd 100644 --- a/Sources/CombineLongPolling/LongPollingPublisher.swift +++ b/Sources/CombineLongPolling/LongPollingPublisher.swift @@ -44,7 +44,7 @@ extension LongPollingPublisher { private var started = false private var finished = false private var currentRequest: AnyCancellable? - private var semaphore = DispatchSemaphore(value: 1) + private var semaphore = DispatchSemaphore(value: 0) init(dataTaskPublisher: AnyPublisher<(data: Data, response: URLResponse), URLError>, subscriber: S) { self.dataTaskPublisher = dataTaskPublisher @@ -83,7 +83,11 @@ extension LongPollingPublisher { } private func start() { - self.semaphore = DispatchSemaphore(value: 1) + // Instead of creating the semaphore with value 1, we signal() immediately to increase the value to 1. This workaround fixes the + // "Semaphore object deallocated while in use"-crash. See https://lists.apple.com/archives/cocoa-dev/2014/Apr/msg00485.html + // Seal of approvoal: "Greg Parker stated that it’s a feature, not a bug" 🦭 + self.semaphore = DispatchSemaphore(value: 0) + self.semaphore.signal() startPolling() } @@ -94,6 +98,7 @@ extension LongPollingPublisher { self.lock.lock() return self.started && !self.finished }() ) { + // on the first run, the semaphore is 1, so we are not blocked here and fetch the data immediately. self.semaphore.wait() self.currentRequest = self.dataTaskPublisher