okhttp interceptor throw SocketTimeoutException caused the crash
erichyx opened this issue · 7 comments
I use retrofit2 and interface return Deferred object, then I got an SocketTimeoutException using the okhttp interceptor, the whole app crashed.
Before using the coroutine, this SocketTimeoutException will not cause app crash, so I don't know how to deal with this problem.
interface api {
@get("info")
fun request(): Deferred
}
class RequestInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response? {
var request = chain.request()
// do something
return chain.proceed(request)
}
}
when I disconnect the network to request and get a retrofit2.httpexception, the app also crashed.
I have used the safeApiCall function to catch exceptions per network request.
suspend fun safeApiCall(call: suspend () -> Response): Response {
return try {
call()
} catch (e: Exception) {
Response.error(IOException(e))
}
}
I seem to have a problem in the same area. But have no idea as to what exactly the problem is. Here is my stacktrace. I have also opened an issue in the retrofit project, but this might be more appropriate.
Also, I can not reproduce my crash. It only happens sporadically.
com.crashlytics.android.core.CrashlyticsBackgroundWorker.submitAndWait (SourceFile:43)
--
| com.crashlytics.android.core.CrashlyticsController.handleUncaughtException (SourceFile:285)
| com.crashlytics.android.core.CrashlyticsController$5.onUncaughtException (SourceFile:269)
| com.crashlytics.android.core.CrashlyticsUncaughtExceptionHandler.uncaughtException (SourceFile:30)
| java.lang.ThreadGroup.uncaughtException (ThreadGroup.java:1068)
| java.lang.ThreadGroup.uncaughtException (ThreadGroup.java:1063)
| kotlinx.coroutines.CoroutineExceptionHandlerImplKt.handleCoroutineExceptionImpl (SourceFile:35)
| kotlinx.coroutines.CoroutineExceptionHandlerKt.handleExceptionViaHandler (SourceFile:47)
| kotlinx.coroutines.CoroutineExceptionHandlerKt.handleCoroutineException (SourceFile:31)
| kotlinx.coroutines.CoroutineExceptionHandlerKt.handleCoroutineException$default (SourceFile:24)
| kotlinx.coroutines.AbstractContinuation.handleException (SourceFile:254)
| kotlinx.coroutines.AbstractContinuation.initParentJobInternal$kotlinx_coroutines_core (SourceFile:206)
| kotlinx.coroutines.AbstractContinuation.initParentJobInternal$kotlinx_coroutines_core (SourceFile:144)
| kotlinx.coroutines.ResumeAwaitOnCompletion.invoke (SourceFile:1236)
| kotlinx.coroutines.JobSupport.notifyCompletion (SourceFile:1351)
| kotlinx.coroutines.JobSupport.tryFinalizeFinishingState (SourceFile:292)
| kotlinx.coroutines.JobSupport.tryFinalizeFinishingState (SourceFile:225)
| kotlinx.coroutines.JobSupport.tryFinalizeFinishingState (SourceFile:792)
| kotlinx.coroutines.JobSupport.makeCompleting$kotlinx_coroutines_core (SourceFile:715)
| kotlinx.coroutines.CompletableDeferredImpl.completeExceptionally (SourceFile:72)
| com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory$BodyCallAdapter$adapt$2.onFailure (SourceFile:97)
| retrofit2.OkHttpCall$1.callFailure (SourceFile:135)
| retrofit2.OkHttpCall$1.onFailure (SourceFile:130)
| okhttp3.RealCall$AsyncCall.execute (SourceFile:215)
| okhttp3.internal.NamedRunnable.run (SourceFile:32)
| java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1162)
@vitoksmile It doesn't work, here is my code snippet.
val parentJob = SupervisorJob()
val uiScope = CoroutineScope(Dispatchers.Main + parentJob)
uiScope.launch {
safeApiCall {
api.getXXX(Id).await()
}
}
suspend fun safeApiCall(call: suspend () -> Response): Response {
return try {
call()
} catch (e: Throwable) {
Response.error(e)
}
}
I had the same problem. It seems that upgrading coroutines to version 1.1.1 solved this for me. I had version 1.0.0 before. My code:
private val mJob = SupervisorJob()
private val mScope = CoroutineScope(Dispatchers.Main + mJob)
fun fetchAllData() {
mScope.launch(Dispatchers.IO) {
try {
val fetchResult = configApi.getSettingsAsync()
val result= fetchResult.await()
Log.d(TAG, "Received result ${result?.id}")
} catch (se: SocketTimeoutException) {
Log.e(TAG, "Error: ${se.message}")
...
} catch (ex: Throwable) {
Log.e(TAG, "Error ${ex.message}")
...
}
}
}
override fun onCleared() {
super.onCleared()
mScope.coroutineContext.cancelChildren()
}
Hello, is there any way to catch the exceptions in any other way? This means i have to add try catch for every call. I don't see this very convenience.
Hello, this also happens if you have a CoroutineWorker
that calls a Deferred<Response<T>>
when the user connection is not stable if crashes when a SocketTimeout
is thrown.
Any ideas on this?