question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Avoiding deadlocks within okhttp interceptors/authenticator when using retrofit with coroutines adapter

See original GitHub issue

Hi, I used retrofit+okhttp+rxjava, now migrated to coroutines. These have implicit support and from what I know the coroutine adapter is hardcoded to use okhttp’s thread dispatcher (not the caller context, as it was possible with rxjava; the async boolean parameter)

What happens now is that, there are cases where requests need to be initiated from within okhttp’s interceptors/authenticator; which are ran on okhttp’s threads

From what I gather, that threadpool is limited, therefore calling new request when the thread pool is maxed out, will lead to deadlock

(Just for clarification, the pseudo-codey situation is this)

fun OkhttpAuthenticator.authenticate() {
	...
	synchronized(this) {
		runBlocking { retrofitService.suspendingRefreshTokens() }<--- 
		...
	}
}

What is the recommended solution for this?

Having the auth calls declared as synchronous in retrofit? Drive auth layers via a custom (separate) dispatcher? Make dispatcher smart enought not to hop from okhttp thread to okhttp thread? Is there option to not use okhttp’s threadpools as it was in rxjava?

I know this might be out of retrofit scope, but I believe many implementations in the wild have this issue

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5

github_iconTop GitHub Comments

1reaction
ursusursuscommented, Jan 5, 2022

For the calls which needed be called from within okhttp thread I kept them blocking, i.e. no threading applied, returning plain Call<T>. Then for convenience I wrapped it with this

/** Due to the fact that native retrofit coroutines support
 * runs request on OkHttp thread pool, which is hard limited.
 * Refreshing tokens happens from within a Authenticator,
 * which is already run on OkHttp thread, thus resulting in
 * OkHttp thread requesting to spawn another OkHttp thread,
 * which leads to deadlock.
 * Workaround was either run all such requests synchronously,
 * or, as here, simply run them on IO dispatcher, which is
 * unbounded.*/
private suspend fun <T> Call<T>.suspendExecute(): Response<T> {
    return withContext(dispatcherProvider.io) {
        suspendCancellableCoroutine { continuation ->
            continuation.invokeOnCancellation {
                cancel()
            }

            try {
                val response: Response<T> = execute()
                continuation.resume(response)
            } catch (ex: Exception) {
                continuation.resumeWithException(ex)
            }
        }
    }
}

(btw nazdar)

0reactions
ywett02commented, Jan 6, 2022

I deduced it from seeing the following in logs: image

Anyway, I am not any okhttp or threads expert. Maybe I was not looking at the correct place.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Avoiding deadlocks within okhttp interceptors/authenticator ...
Hi, I used retrofit+okhttp+rxjava, now migrated to coroutines. These have implicit support and from what I know the coroutine adapter is ...
Read more >
Authenticator breaking when refreshing tokens with coroutines ...
I'd say it's interaction of okhttp backed retrofit when using okhttp threadpool. I mean the deadlock is pretty obvious (okhttp thread trying ...
Read more >
Kotlin Coroutines and Retrofit - Medium
According to the Kotlin docs it is stated that coroutines are a lightweight alternative to threads. “Coroutines provide a way to avoid blocking...
Read more >
retrofit - bytemeta
retrofit repo issues. ... Avoiding deadlocks within okhttp interceptors/authenticator when using retrofit ... Update protobuf version for converter-protobuf.
Read more >
Issues - okhttp - Square - Geeks
Avoiding deadlocks within okhttp interceptors/authenticator when using retrofit with coroutines adapter. #6754 opened a year ago.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found