简体   繁体   中英

RequestRetrier Alamofire lock not working

I'm implementing a RequestRetrier with Alamofire to refresh the accessToken of a given user.

func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
    lock.lock() ; defer { lock.unlock() }

    if let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 {
        requestsToRetry.append(completion)

        if !isRefreshing {
            refreshToken(completion: { [weak self] succeded, accessToken in

                guard let strongSelf = self else { return }

                strongSelf.lock.lock() ; defer { strongSelf.lock.unlock() }

                strongSelf.requestsToRetry.forEach{ $0(succeded, 0.0) }
                strongSelf.requestsToRetry.removeAll()
            })
        }
    } else {
        completion(false, 0.0)
    }
}

When strongSelf.lock.lock() ; defer { strongSelf.lock.unlock() } strongSelf.lock.lock() ; defer { strongSelf.lock.unlock() } is called it doesn't continue the execution so I have an infinite loop. I tried checking the result of strongSelf.lock.try() and returns false.

This is happening when I sign in with a wrong password so the server returns a 401.

This is my refreshToken code

guard !isRefreshing else { return }

// ... Get user ... //
if let user = user {

    isRefreshing = true
    signIn(user: userDTO)
        .subscribe(onNext: { [weak self] userSession in
            guard let strongSelf = self else { return }
            // ... Save accessToken ... //
            completion(true, userSession.accessToken)
            strongSelf.isRefreshing = false
        }, onError: { [weak self] error in
            guard let strongSelf = self else { return }
            // ... Log out user ... //
            completion(false, nil)
            strongSelf.isRefreshing = false
        })
        .disposed(by: bag)
} else {
        completion(false, nil)
}

As seen in the Github issue https://github.com/Alamofire/Alamofire/issues/2544 I could fix this by changing:

private let lock = NSLock()

to

private let lock = NSRecursiveLock()

The difference between them is that the recursive lock can by unlocked if the same thread is trying to lock.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM