Skip to content

Commit

Permalink
Fixes Crashing When Using Background Requests (#16)
Browse files Browse the repository at this point in the history
# Fixes Crashing When Using Background Requests

## ♻️ Current situation & Problem
- if a developer uses multiple HealthKit queries in the background data
races accessing the tracked background activations can lead to runtime
crashes.


## ⚙️ Release Notes 
- Fixes the issue using additional locking mechanisms

## 📝 Code of Conduct & Contributing Guidelines 

By submitting creating this pull request, you agree to follow our [Code
of
Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md):
- [x] I agree to follow the [Code of
Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md).
  • Loading branch information
PSchmiedmayer authored Feb 20, 2024
1 parent d882734 commit b40695f
Showing 1 changed file with 19 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import Spezi


extension HKHealthStore {
static var activeObservations: [HKObjectType: Int] = [:]
private static var activeObservations: [HKObjectType: Int] = [:]
private static let activeObservationsLock = NSLock()


func startObservation(
Expand Down Expand Up @@ -48,9 +49,7 @@ extension HKHealthStore {

continuation.onTermination = { @Sendable _ in
self.stop(observerQuery)
Task {
await self.disableBackgroundDelivery(for: sampleTypes)
}
self.disableBackgroundDelivery(for: sampleTypes)
}
}
}
Expand All @@ -68,28 +67,32 @@ extension HKHealthStore {
for objectType in objectTypes {
try await self.enableBackgroundDelivery(for: objectType, frequency: frequency)
enabledObjectTypes.insert(objectType)
HKHealthStore.activeObservations[objectType] = HKHealthStore.activeObservations[objectType, default: 0] + 1
Self.activeObservationsLock.withLock {
HKHealthStore.activeObservations[objectType] = HKHealthStore.activeObservations[objectType, default: 0] + 1
}
}
} catch {
// Revert all changes as enable background delivery for the object types failed.
await disableBackgroundDelivery(for: enabledObjectTypes)
disableBackgroundDelivery(for: enabledObjectTypes)
}
}


func disableBackgroundDelivery(
for objectTypes: Set<HKObjectType>
) async {
) {
for objectType in objectTypes {
if let activeObservation = HKHealthStore.activeObservations[objectType] {
let newActiveObservation = activeObservation - 1
if newActiveObservation <= 0 {
HKHealthStore.activeObservations[objectType] = nil
do {
try await self.disableBackgroundDelivery(for: objectType)
} catch {}
} else {
HKHealthStore.activeObservations[objectType] = newActiveObservation
Self.activeObservationsLock.withLock {
if let activeObservation = HKHealthStore.activeObservations[objectType] {
let newActiveObservation = activeObservation - 1
if newActiveObservation <= 0 {
HKHealthStore.activeObservations[objectType] = nil
Task {
try await self.disableBackgroundDelivery(for: objectType)
}
} else {
HKHealthStore.activeObservations[objectType] = newActiveObservation
}
}
}
}
Expand Down

0 comments on commit b40695f

Please sign in to comment.