Home > Enterprise >  OkHttpClient with Java Future java.io.InterruptedIOException
OkHttpClient with Java Future java.io.InterruptedIOException

Time:10-10

I am trying to make a web scraper that parses specific URL indefinitely with some delay in between. I have a method genericMonitor that accepts the url to parse and a callback to return a result. This method is called repeatedly using SheduledExecutorService. The code is below:

ScheduledFuture<?> task = service.scheduleWithFixedDelay(() -> {
          try {
            genericMonitor(percent, url, idSupplier, callback);
          } catch (IOException connectException) {
            logger.error("Error in generic", connectException);
          }
        }, 0, delay, TimeUnit.MINUTES);
        tasks.put(link, task);

The tasks map holds all currently running tasks. I make http requests using OkHttp Java library. When I try to cancel the task using task.cancel I get InterruptedIOException:

java.io.InterruptedIOException: interrupted
    at okio.Timeout.throwIfReached(Timeout.java:146)
    at okio.Okio$1.write(Okio.java:76)
    at okio.AsyncTimeout$1.write(AsyncTimeout.java:180)
    at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.java:179)
    at okio.RealBufferedSink.writeByte(RealBufferedSink.java:125)
    at okhttp3.internal.http2.Http2Writer.writeMedium(Http2Writer.java:265)
    at okhttp3.internal.http2.Http2Writer.frameHeader(Http2Writer.java:253)
    at okhttp3.internal.http2.Http2Writer.headers(Http2Writer.java:289)
    at okhttp3.internal.http2.Http2Connection.newStream(Http2Connection.java:253)
    at okhttp3.internal.http2.Http2Connection.newStream(Http2Connection.java:225)
    at okhttp3.internal.http2.Http2Codec.writeRequestHeaders(Http2Codec.java:117)
    at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:54)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:94)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:125)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:264)
    at okhttp3.RealCall.execute(RealCall.java:93)
    at org.dk.Bot.callRemoteWithProxy(Bot.java:82)
    at org.dk.Bot.genericMonitor(Bot.java:182)
    at org.dk.Bot.lambda$processCommand$1(Bot.java:129)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
    at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at java.base/java.lang.Thread.run(Thread.java:832)

I am not sure what's the problem

CodePudding user response:

From Oracle documentation of the class InterruptedIOException :

  • Signals that an I/O operation has been interrupted. An
  • InterruptedIOException is thrown to indicate that an
  • input or output transfer has been terminated because the thread
  • performing it was interrupted. The field {@link #bytesTransferred}
  • indicates how many bytes were successfully transferred before
  • the interruption occurred.

You are trying to cancel or interrup a thread who execute an IO operation , i think in the method "genericMonitor" you have some IO operations , or you are trying to interrupt the thread when he is in the catch block writing in the log file , so that's why you got this type of exception.

You can add isDone before calling cancel to be sure that the exception will not be thrown . or you can handle this Exception and be sure that all of your ressources are closed ( try with ressources) , this link give you an idea about how to handle a similar exception type : Handling InterruptedException in Java .

You can use also : boolean cancel(boolean mayInterruptIfRunning); Try to read the documentation of this method and see if it can help you .

CodePudding user response:

The exception is thrown when you call cancel with parameter mayInterruptIfRunning set to true.

... If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task. ...

Parameters: mayInterruptIfRunning - true if the thread executing this task should be interrupted; otherwise, in-progress tasks are allowed to complete

Hence it will interrupt the task and cause InterruptedIOException inside your running task. If you want to allow in-progress task to complete, call cancel(false) instead.

  • Related