Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash in ProductsInfoController.retrieveProductsInfo #468

Open
4 of 9 tasks
carbonimax opened this issue May 21, 2019 · 7 comments
Open
4 of 9 tasks

Crash in ProductsInfoController.retrieveProductsInfo #468

carbonimax opened this issue May 21, 2019 · 7 comments
Labels
difficulty: advanced we really need help with this one help wanted status: code review need to review the code type: bug

Comments

@carbonimax
Copy link

Platform

  • iOS
  • macOS
  • tvOS

In app purchase type

  • Consumable
  • Non-consumable
  • Auto-Renewable Subscription
  • Non-Renewing Subscription

Environment

  • Sandbox
  • Production

Version

0.15.0

Report

Issue summary

sometimes, it crash when it retrieve products info.

1  SwiftyStoreKit                 0x101497258 partial apply for closure #1 in InAppProductQueryRequest.performCallback(_:) (InAppProductQueryRequest.swift:76)
    2  SwiftyStoreKit                 0x1014a0f34 thunk for @escaping @callee_guaranteed () -> () (<compiler-generated>)
3  libdispatch.dylib              0x2320bca38 _dispatch_call_block_and_release + 24
4  libdispatch.dylib              0x2320bd7d4 _dispatch_client_callout + 16
5  libdispatch.dylib              0x23209d9e4 _dispatch_main_queue_callback_4CF$VARIANT$armv81 + 1008
6  CoreFoundation                 0x23260dec0 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
7  CoreFoundation                 0x232608df8 __CFRunLoopRun + 1924
8  CoreFoundation                 0x232608354 CFRunLoopRunSpecific + 436
9  GraphicsServices               0x23480879c GSEventRunModal + 104
10 UIKitCore                      0x25ebf3b68 UIApplicationMain + 212
11 app.                               0x100438400 main (main.m:14)
12 libdyld.dylib                  0x2320ce8e0 start + 4```
@gianpispi
Copy link

I have the same issue!

@tamir-maoz
Copy link

Same here

@RamblinWreck77
Copy link

+1

@astrokin
Copy link

inflightRequests should be thread safe

@gerchicov-bp
Copy link

gerchicov-bp commented Dec 26, 2019

Do you have concrete simple steps to reproduce/simulate this bug?

@Sam-Spencer
Copy link
Collaborator

Hello all! Please check out the latest commit on the develop branch to see if this issue has been resolved (thanks to @cipolleschi and PR #495).

@Sam-Spencer Sam-Spencer added difficulty: advanced we really need help with this one help wanted status: code review need to review the code type: bug labels Aug 15, 2020
@NikKovIos
Copy link

NikKovIos commented Jun 9, 2021

70761d2 is reverting the #495
So the crash still can accure. Also there are 3 force unwraps! It's bad idea.

Like a workaround you can downgrade to old implementation (like i did):

class ProductsInfoController: NSObject {
    struct InAppProductQuery {
        let request: InAppProductRequest
        var completionHandlers: [InAppProductRequestCallback]
    }

    // As we can have multiple inflight requests, we store them in a dictionary by product ids
    private let inflightRequestsQueue = DispatchQueue(label: "InflightRequestsQueue", attributes: .concurrent)
    private var threadInflightRequests: [Set<String>: InAppProductQuery] = [:]
    private var inflightRequests: [Set<String>: InAppProductQuery] {
        get {
            return inflightRequestsQueue.sync {
                return threadInflightRequests
            }
        }
        set {
            inflightRequestsQueue.async(flags: .barrier) {
                self.threadInflightRequests = newValue
            }
        }
    }

    func retrieveProductsInfo(_ productIds: Set<String>, completion: @escaping (RetrieveResults) -> Void) {
        guard !Thread.current.isMainThread else {
            DispatchQueue.global().async { [weak self] in
                self?.retrieveProductsInfo(productIds, completion: completion)
            }
            return
        }
        if inflightRequests[productIds] == nil {
            let request = InAppProductQueryRequest(productIds: productIds) { results in
                if let query = self.inflightRequests[productIds] {
                    for completion in query.completionHandlers {
                        completion(results)
                    }
                    self.inflightRequests[productIds] = nil
                } else {
                    // should not get here, but if it does it seems reasonable to call the outer completion block
                    completion(results)
                }
            }
            inflightRequests[productIds] = InAppProductQuery(request: request, completionHandlers: [completion])
            request.start()
        } else {
            inflightRequests[productIds]?.completionHandlers.append(completion)
        }
    }

    func cancelAllInflightRequests() {
        guard !Thread.current.isMainThread else {
            DispatchQueue.global().async { [weak self] in
                self?.cancelAllInflightRequests()
            }
            return
        }
        inflightRequests.forEach({ $0.value.request.cancel() })
        inflightRequests.removeAll()
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
difficulty: advanced we really need help with this one help wanted status: code review need to review the code type: bug
Projects
None yet
Development

No branches or pull requests

8 participants