aleixrr
aleixrr

Reputation: 489

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() } 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)
}

Upvotes: 4

Views: 868

Answers (1)

aleixrr
aleixrr

Reputation: 489

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.

Upvotes: 1

Related Questions