Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HttpLoggingInterceptor causes stackoverflow #2962

Closed
agustinsivoplas opened this issue Nov 7, 2016 · 5 comments
Closed

HttpLoggingInterceptor causes stackoverflow #2962

agustinsivoplas opened this issue Nov 7, 2016 · 5 comments

Comments

@agustinsivoplas
Copy link

I have this class to create a service with retrofit2 + rxandroid + okhttp.

public class ServiceCreator {

    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
    private static final int DEFAULT_TIMEOUT = 30; //seconds

    private static Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create();
    private static RxJavaCallAdapterFactory rxAdapter = RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io());

    private static Retrofit.Builder builder = new Retrofit.Builder()
            .baseUrl(BuildConfig.REST_BASE_ENDPOINT)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(rxAdapter);

    public static <RESTService> RESTService createService(Class<RESTService> service, String userToken) {

        if (BuildConfig.REST_DEBUG) {
            HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            httpClient.addInterceptor(logging);
        }

        if (StringUtils.isNotBlank(userToken)) {
            httpClient.addInterceptor(chain -> {
                Request original = chain.request();

                Request request = original.newBuilder()
                        .header(Constants.AUTHORIZATION_HEADER, userToken)
                        .method(original.method(), original.body())
                        .build();
                return chain.proceed(request);
            });
        }

        httpClient.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        httpClient.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        httpClient.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);

        Retrofit retrofit = builder.client(httpClient.build()).build();
        return retrofit.create(service);
    }

    public static Retrofit retrofit() {
        return builder.client(httpClient.build()).build();
    }
}

This code causes an stackoverflow error in android kitkat.


FATAL EXCEPTION: RxNewThreadScheduler-1 java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread.
   at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:59)
   at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
   at java.util.concurrent.FutureTask.run(FutureTask.java:237)
   at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
   at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
   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:841)
Caused by: java.lang.StackOverflowError
   at org.apache.harmony.security.asn1.ASN1StringType.getDecodedObject(ASN1StringType.java:99)
   at org.apache.harmony.security.asn1.ASN1StringType.decode(ASN1StringType.java:90)
   at org.apache.harmony.security.asn1.ASN1Choice.decode(ASN1Choice.java:308)
   at org.apache.harmony.security.x501.AttributeTypeAndValue$1.decode(AttributeTypeAndValue.java:339)
   at org.apache.harmony.security.asn1.BerInputStream.readSequence(BerInputStream.java:554)
   at org.apache.harmony.security.asn1.DerInputStream.readSequence(DerInputStream.java:105)
   at org.apache.harmony.security.asn1.ASN1Sequence.decode(ASN1Sequence.java:40)
   at org.apache.harmony.security.asn1.BerInputStream.decodeValueCollection(BerInputStream.java:626)
   at org.apache.harmony.security.asn1.BerInputStream.readSetOf(BerInputStream.java:606)
   at org.apache.harmony.security.asn1.DerInputStream.readSetOf(DerInputStream.java:115)
   at org.apache.harmony.security.asn1.ASN1SetOf.decode(ASN1SetOf.java:40)
   at org.apache.harmony.security.asn1.BerInputStream.decodeValueCollection(BerInputStream.java:626)
   at org.apache.harmony.security.asn1.BerInputStream.readSequenceOf(BerInputStream.java:584)
   at org.apache.harmony.security.asn1.ASN1SequenceOf.decode(ASN1SequenceOf.java:40)
   at org.apache.harmony.security.asn1.ASN1Type.decode(ASN1Type.java:82)
   at javax.security.auth.x500.X500Principal.<init>(X500Principal.java:78)
   at com.android.org.conscrypt.OpenSSLX509Certificate.getIssuerX500Principal(OpenSSLX509Certificate.java:422)
   at com.android.org.conscrypt.OpenSSLX509Certificate.getIssuerDN(OpenSSLX509Certificate.java:236)
   at com.android.org.conscrypt.TrustManagerImpl.cleanupCertChainAndFindTrustAnchors(TrustManagerImpl.java:340)
   at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:225)
   at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:202)
   at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:611)
   at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
   at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:405)
   at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:241)
   at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:198)
   at okhttp3.internal.connection.RealConnection.buildConnection(RealConnection.java:174)
   at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:114)
   at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:193)
   at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:129)
   at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:98)
   at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
   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:109)
   at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)

But if I remove this line of code, works perfect.

        if (BuildConfig.REST_DEBUG) {
            HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            httpClient.addInterceptor(logging);
        }

I have uses this class without RxAndroid and works perfect with this versions:

compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'

Nowadays I'm using:

compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
compile 'com.squareup.okhttp3:okhttp:3.4.1'
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'

Also I have created a stackoverflow question: http://stackoverflow.com/questions/40441957/retrofit-rxandroid-causes-stackoverflow-error-on-kitkat

Thanks

@tachang
Copy link

tachang commented Nov 7, 2016

I wonder if this has to do with #2961 as well.

I fixed it by setting the log level to headers.

            logging.setLevel(HttpLoggingInterceptor.Level.HEADER);

@JakeWharton
Copy link
Member

Are you calling createService every time you need to make a request? Because you're adding the same interceptor over and over and over.

Please provide an executable test case.

@agustinsivoplas
Copy link
Author

@JakeWharton You are right, I was adding the same interceptor over and over. Sorry

@dibyendumr
Copy link

Thanks a lot to @agustinsivoplas for the very rarely foudn solution to the one of most trivial problems on OkHttp and retrofit. Equally thanks to @tachang. I was struggling with a solution and in want of a solution very badly I found this article and to my surprise it worked.

As I found out if you remove

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
httpClient.addInterceptor(logging);

OR as @tachang said to make the log level to:
logging.setLevel(HttpLoggingInterceptor.Level.HEADER);

Thanks again to all...

@agustinsivoplas
Copy link
Author

@dibyendumr Glad to help. Thank you for the great library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants