我有一个资源可能会运行很长时间的阻塞操作。在实际代码中,它是一个ZeroMQ例程,等待下一条消息(与示例代码here不太相似),但是在此示例中,我创建了一个虚拟循环,该循环仅在关闭资源时终止。问题是,如果我用ctrl+c
中断执行,则会收到异常,循环将继续运行,并且close
仅在我第二次点击ctrl+c
时才被调用。我想如果应用程序异常终止也会发生同样的情况。
这是资源定义:
class DummyLoop extends Closeable {
var running = true
def run() = {
while (running) {
println("sleeping")
Thread.sleep(1000)
}
}
override def close(): Unit = {
println("closing...")
running = false
}
}
def dummyLoop(): Resource[IO, DummyLoop] =
Resource.fromAutoCloseable(IO(new DummyLoop))
然后从main
开始,我这样使用它:
def run(args: List[String]): IO[ExitCode] = {
dummyLoop()
.use {
dl =>
for {
_ <- IO(dl.run())
} yield ExitCode.Success
}
}
我希望在执行中断时调用close
方法。相反,我得到了:
...
# {----------------HERE THE PROGRAMME STARTS TO RUN NORMALLY}
[info] running TestApp
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
# {----------------HERE I HIT THE FIRST CTRL+C}
^C
[warn] Canceling execution...
[error] Total time: 9 s, completed 30 Oct 2019, 18:11:50
[warn] Run canceled.
[error] (run-main-0) java.lang.InterruptedException
Exception in thread "sbt-bg-threads-1" java.util.concurrent.RejectedExecutionException
at java.base/java.util.concurrent.ForkJoinPool.externalPush(ForkJoinPool.java:1889)
at java.base/java.util.concurrent.ForkJoinPool.externalSubmit(ForkJoinPool.java:1930)
at java.base/java.util.concurrent.ForkJoinPool.execute(ForkJoinPool.java:2462)
at scala.concurrent.impl.ExecutionContextImpl.execute(ExecutionContextImpl.scala:24)
at sbt.internal.BackgroundThreadPool$BackgroundRunnable.$anonfun$cleanup$1(DefaultBackgroundJobService.scala:390)
at sbt.internal.BackgroundThreadPool$BackgroundRunnable.$anonfun$cleanup$1$adapted(DefaultBackgroundJobService.scala:389)
at scala.collection.immutable.List.foreach(List.scala:392)
at sbt.internal.BackgroundThreadPool$BackgroundRunnable.cleanup(DefaultBackgroundJobService.scala:389)
at sbt.internal.BackgroundThreadPool$BackgroundRunnable.run(DefaultBackgroundJobService.scala:359)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:830)
[error] java.lang.InterruptedException
[error] at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1040)
[error] at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1345)
[error] at cats.effect.internals.IOPlatform$.$anonfun$unsafeResync$2(IOPlatform.scala:50)
[error] at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23)
[error] at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:57)
[error] at scala.concurrent.package$.blocking(package.scala:146)
[error] at cats.effect.internals.IOPlatform$.unsafeResync(IOPlatform.scala:50)
[error] at cats.effect.IO.unsafeRunTimed(IO.scala:325)
[error] at cats.effect.IO.unsafeRunSync(IO.scala:240)
[error] at cats.effect.internals.IOAppPlatform$.main(IOAppPlatform.scala:24)
[error] at cats.effect.IOApp.main(IOApp.scala:67)
[error] at cats.effect.IOApp.main$(IOApp.scala:66)
[error] at io.tokenanalyst.bitcoinrpc.TestApp$.main(TestApp.scala:25)
[error] at io.tokenanalyst.bitcoinrpc.TestApp.main(TestApp.scala)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error] at java.base/java.lang.reflect.Method.invoke(Method.java:567)
[error] stack trace is suppressed; run last Compile / bgRun for the full output
# {-----------THE LOOP KEEPS RUNNING}
sleeping
sleeping
sleeping
# {-----------WHEN I HIT THE SECOND CTRL+C, CLOSE IS CALLED AND THE PROGRAMME FINALLY TERMINATES}
^C[warn] Thread[shutdownHook1,5,run-main-group-0] loading cats.effect.internals.CancelUtils$ after test or run has completed. This is a likely resource leak
closing...
处理这些情况的正确方法是什么?我究竟做错了什么?谢谢!
答案 0 :(得分:0)
最终升级到cats v 2.0.0
解决了该问题。