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.

java.lang.IllegalStateException: Unbalanced enter/exit

See original GitHub issue

Version: 3.9.0

I was investigating a resource leak in Glide which involves lots of parallel requests and adding an try/finally/close in okhttp3.Callback.onResponse:

@Override
public void onResponse(Call call, Response response) throws IOException {
  try {
    responseBody = response.body();
    if (response.isSuccessful()) {
      long contentLength = responseBody.contentLength();
      stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength);
      callback.onDataReady(stream);
    } else {
      callback.onLoadFailed(new HttpException(response.message(), response.code()));
    }
  } finally {
    response.body().close();
  }
}

After a fair amount of scrolling back and forth in Glide’s sample app (producing lots of requests and cancellations), I’ve see this exactly once:

09-10 09:44:32.588 E/AndroidRuntime( 4423): FATAL EXCEPTION: OkHttp Dispatcher
09-10 09:44:32.588 E/AndroidRuntime( 4423): Process: com.bumptech.glide.samples.flickr, PID: 4423
09-10 09:44:32.588 E/AndroidRuntime( 4423): java.lang.IllegalStateException: Unbalanced enter/exit
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at okio.AsyncTimeout.enter(AsyncTimeout.java:73)
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at okio.AsyncTimeout$2.read(AsyncTimeout.java:235)
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at okio.RealBufferedSource.read(RealBufferedSource.java:46)
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at okhttp3.internal.http1.Http1Codec$AbstractSource.read(Http1Codec.java:352)
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at okhttp3.internal.http1.Http1Codec$FixedLengthSource.read(Http1Codec.java:396)
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at okhttp3.internal.Util.skipAll(Util.java:175)
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at okhttp3.internal.Util.discard(Util.java:157)
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at okhttp3.internal.http1.Http1Codec$FixedLengthSource.close(Http1Codec.java:413)
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at okio.RealBufferedSource.close(RealBufferedSource.java:455)
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at okhttp3.internal.Util.closeQuietly(Util.java:110)
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at okhttp3.ResponseBody.close(ResponseBody.java:187)
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at com.bumptech.glide.integration.okhttp3.OkHttpStreamFetcher.onResponse(OkHttpStreamFetcher.java:111)
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at okhttp3.RealCall$AsyncCall.execute(RealCall.java:153)
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
09-10 09:44:32.588 E/AndroidRuntime( 4423): 	at java.lang.Thread.run(Thread.java:761)
09-10 09:44:32.594 W/ActivityManager( 1702):   Force finishing activity com.bumptech.glide.samples.flickr/.FlickrSearchActivity

The close in onResponse above causes lots of additional exceptions on other threads because Glide tries to read the ResponseBody’s InputStream after that point. The try/finally above is only there to help me debug the resource leak. However, it does produce lots of exceptions on background threads, if it’s relevant:

09-10 09:50:35.082 I/Glide   ( 4511): java.io.IOException: closed
09-10 09:50:35.082 I/Glide   ( 4511): 	at okio.RealBufferedSource$1.read(RealBufferedSource.java:426)
09-10 09:50:35.082 I/Glide   ( 4511): 	at java.io.FilterInputStream.read(FilterInputStream.java:133)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.util.ContentLengthInputStream.read(ContentLengthInputStream.java:66)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream.fillbuf(RecyclableBufferedInputStream.java:176)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream.read(RecyclableBufferedInputStream.java:309)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.util.ExceptionCatchingInputStream.read(ExceptionCatchingInputStream.java:85)
09-10 09:50:35.082 I/Glide   ( 4511): 	at java.io.FilterInputStream.read(FilterInputStream.java:133)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.util.MarkEnforcingInputStream.read(MarkEnforcingInputStream.java:45)
09-10 09:50:35.082 I/Glide   ( 4511): 	at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
09-10 09:50:35.082 I/Glide   ( 4511): 	at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:646)
09-10 09:50:35.082 I/Glide   ( 4511): 	at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:622)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.resource.bitmap.Downsampler.decodeStream(Downsampler.java:485)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.resource.bitmap.Downsampler.decodeFromWrappedStreams(Downsampler.java:276)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:204)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder.decode(StreamBitmapDecoder.java:60)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder.decode(StreamBitmapDecoder.java:17)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.resource.bitmap.BitmapDrawableDecoder.decode(BitmapDrawableDecoder.java:45)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.engine.DecodePath.decodeResourceWithList(DecodePath.java:67)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.engine.DecodePath.decodeResource(DecodePath.java:52)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.engine.DecodePath.decode(DecodePath.java:43)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.engine.LoadPath.loadWithExceptionList(LoadPath.java:56)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.engine.LoadPath.load(LoadPath.java:42)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.engine.DecodeJob.runLoadPath(DecodeJob.java:538)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.engine.DecodeJob.decodeFromFetcher(DecodeJob.java:510)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.engine.DecodeJob.decodeFromData(DecodeJob.java:491)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.engine.DecodeJob.decodeFromRetrievedData(DecodeJob.java:445)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:293)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:250)
09-10 09:50:35.082 I/Glide   ( 4511): 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
09-10 09:50:35.082 I/Glide   ( 4511): 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
09-10 09:50:35.082 I/Glide   ( 4511): 	at java.lang.Thread.run(Thread.java:761)
09-10 09:50:35.082 I/Glide   ( 4511): 	at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:347)

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
swankjessecommented, Dec 30, 2017

I’m curious about this line:

 callback.onDataReady(stream); 

Could that cause the stream to be consumed by another thread? In that case we’ve got one thread reading while OkHttp’s dispatcher thread is closing.

0reactions
sjuddcommented, Dec 30, 2017

Yeah sorry this wasn’t clear in my original explanation, the callbacks will post the stream to other threads that will then try to read from them.

Passing closed streams to other threads won’t happen in normal circumstances in Glide, which probably explains why I haven’t seen this more frequently either.

Read more comments on GitHub >

github_iconTop Results From Across the Web

java.lang.IllegalStateException: Unbalanced enter/exit #6318
Our usage, which is in a rabbitmq consumer. We use com.squareup.okhttp3:okhttp:3.9.1 and openjdk version "1.8.0_242".
Read more >
Unbalanced enter/exit on OkHttp - Stack Overflow
So I have an exception every so often that says java.lang.IllegalStateException: Unbalanced enter/exit and this happens when the onStop of ...
Read more >
Android app Crash from exception Java.Lang ... - MSDN
Boolean throwOnFirstException) java.lang.IllegalStateException: Unbalanced enter/exit com.android.okhttp.okio.
Read more >
okio/okio/src/main/java/okio/AsyncTimeout.java - Google Git
if (inQueue) throw new IllegalStateException("Unbalanced enter/exit");. long timeoutNanos = timeoutNanos();. boolean hasDeadline = hasDeadline();.
Read more >
java.lang.IllegalStateException: Unbalanced enter/exit
Version: 3.9.0. I was investigating a resource leak in Glide which involves lots of parallel requests and adding an try/finally/close in ...
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