1
votes

I have an Android project developed using sdk version 25. I'm using RXJava as my thread management and Retrofit library for hit the network.

I also implemented custom Interceptor for adding override fun intercept(chain: Interceptor.Chain): Response? {

    val request = addHeader(chain)

    val response = chain.proceed(request)
    checkErrorResponse(response)

    return response

The api call will always inside the RX Java flow and I'm making sure of it. After I put my APK to the Playstore, a crash is detected by Crashlytics.

#0. Crashed: main: 0 0 0x0000000000000000
   at okio.Okio$4.newTimeoutException(Okio.java:230)
   at okio.AsyncTimeout.exit(AsyncTimeout.java:285)
   at okio.AsyncTimeout$2.read(AsyncTimeout.java:241)
   at okio.RealBufferedSource.indexOf(RealBufferedSource.java:345)
   at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:217)
   at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:211)
   at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:189)
   at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:75)
   at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
   at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
   at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
   at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
   at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
   at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
   at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
   at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
   at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
   at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
   at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
   at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
   at com.payfazz.data.base.net.PayfazzInterceptor.intercept(PayfazzInterceptor.kt:24)
   at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
   at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
   at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:185)
   at okhttp3.RealCall.execute(RealCall.java:69)
   at retrofit2.OkHttpCall.execute(OkHttpCall.java:180)
   at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:41)
   at io.reactivex.Observable.subscribe(Observable.java:10842)
   at io.reactivex.internal.operators.observable.ObservableMap.subscribeActual(ObservableMap.java:33)
   at io.reactivex.Observable.subscribe(Observable.java:10842)
   at io.reactivex.internal.operators.observable.ObservableMap.subscribeActual(ObservableMap.java:33)
   at io.reactivex.Observable.subscribe(Observable.java:10842)
   at io.reactivex.internal.operators.observable.ObservableDefer.subscribeActual(ObservableDefer.java:39)
   at io.reactivex.Observable.subscribe(Observable.java:10842)
   at io.reactivex.internal.operators.observable.ObservableDefer.subscribeActual(ObservableDefer.java:39)
   at io.reactivex.Observable.subscribe(Observable.java:10842)
   at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
   at io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker$BooleanRunnable.run(ExecutorScheduler.java:260)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
   at java.lang.Thread.run(Thread.java:818)

As I investigated the stacktrace, I found my code here exactly at my custom interceptor. And as far as I know, the crash is caused by SocketTimeoutException, then a timed out request. Then I try to reproduce the timeout but it cannot be done. In my environment the exception is always catched by RX Java and sent to onError() method.

How can the crash not catched by RX Java? Should I wrap proceed() method with catch block just for safety?

1
Did you find a fix for this? I am getting the same issue and it is crashing my app. - dazza5000
I have such kind of problem if server is not running when my client is trying to send a request to it. - isabsent

1 Answers

0
votes

These kinds of crashes are caused when an exception is thrown outside of the RxJava lifecycle. This means your exception can be caused by either of these options:

  1. Going by the retrofit sourcecode, there might be a race condition where Disposable.dispose() is called but the timeout occurs before the underlying Call is cancelled. This would cause the timeout to be sent to the observer after it has been disposed, triggering the crash.
  2. An error is thrown inside of the onError handler. This should not occur according to the RxJava protocol and will cause a crash with a CompositeException. Since the error you've posted does not include the exact Exception class this cannot be ruled out.