ACINQ / phoenix

Phoenix is a self-custodial Bitcoin wallet using Lightning to send/receive payments.
https://phoenix.acinq.co
Apache License 2.0
616 stars 93 forks source link

(ios) Revert: Integrate Touchlab's SKIE #551

Closed robbiehanson closed 2 months ago

robbiehanson commented 2 months ago

We were experiencing app freezes in production. The root cause of the problem was Touchlab's SKIE. In particular, an unexpected quirk of the SKIE implementation.

Consider this Swift code:

Task { @MainActor in
   self.fetched = try await paymentsManager.fetcher.getPayment(
      row: row,
      options: PaymentCell.fetchOptions
   )
}

Here we're calling a suspend function in Kotlin (getPayment) from Swift. Now it has always been the case this must be done on the main thread (e.g. MainActor). In fact if you tried from a background thread, Kotlin would throw an exception. It has also been the case that getPayment executes on the main thread.

In recent versions of Kotlin, this main-thread restriction could be removed with a flag.

It appears that SKIE automatically sets this flag. From their docs

Another limitation is that these suspend functions can only be called from the main thread. This limitation can be solved without SKIE by passing a special configuration flag to the compiler. However, SKIE adds this support out of the box.

The end result is that multiple instances of getPayment are running simultaneously on different background threads, our built-in Cache is getting corrupted, and the linked-list ends up with cycles leading to infinite loops in certain situations.

It's relatively easy to solve this one particular bug. But the bigger issue is that I don't know what other issues this problem might cause. And time is needed to further research the issue.