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

Replace specs2 with munit #4216

Open
wants to merge 20 commits into
base: series/3.x
Choose a base branch
from

Conversation

iRevive
Copy link
Contributor

@iRevive iRevive commented Dec 27, 2024

Follow up to #3787.

The whole PR is purely focused on the migration. There are options to build more usable test abstractions and utilities, but I don't want to do it without proper thinking.

@iRevive iRevive force-pushed the topic/munit-kernel-laws branch from e671306 to d2b73e9 Compare December 27, 2024 19:26
// we try iterating a few times to get canceled in the middle
if (i > Bound) {
IO.pure(skipped(s"attempted $i times and could not reproduce scenario"))
IO.println(s"attempted $i times and could not reproduce scenario")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, it's not a direct equivalent. But I cannot think of anything better.

@iRevive iRevive force-pushed the topic/munit-kernel-laws branch 2 times, most recently from 4c319c2 to 7bc5906 Compare December 27, 2024 20:00
@djspiewak
Copy link
Member

…holy crap

@iRevive
Copy link
Contributor Author

iRevive commented Dec 27, 2024

General 20k LOC changeset. Nothing to worry about 😅

@iRevive
Copy link
Contributor Author

iRevive commented Dec 27, 2024

Specs2 model feels more strict. With munit the following code compiles and the test is green, but it's never being executed:

test("leaky io") {
  IO(sys.error("boom"))
}

The compiler doesn't throw any warning, either.


I hope I didn't miss such cases.

Copy link
Member

@djspiewak djspiewak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NGL, I didn't read through all 11k lines. Did some spot checking around though and left some comments on things that I think probably apply more broadly. Agree we should review carefully. Overall looks good though.

ioapp-tests/src/test/scala/IOAppSpec.scala Outdated Show resolved Hide resolved
build.sbt Show resolved Hide resolved
tests/shared/src/test/scala/cats/effect/IOSuite.scala Outdated Show resolved Hide resolved
ioapp-tests/src/test/scala/IOAppSpec.scala Show resolved Hide resolved
@djspiewak
Copy link
Member

Specs2 model feels more strict. With munit the following code compiles and the test is green, but it's never being executed:

This one is concerning, to be sure. We've historically had a bunch of problems with this, and we do have a ton of tests which throw exceptions in various cases. We should explore our own variant of test probably which is stricter.

@iRevive iRevive force-pushed the topic/munit-kernel-laws branch from 3d60f3f to 9f68a30 Compare December 30, 2024 13:59
@iRevive
Copy link
Contributor Author

iRevive commented Dec 30, 2024

specs2 CI time: 5h 22m
munit CI time: 5h 6m

There's not much difference, assuming we lost a spec parallelism.

@djspiewak
Copy link
Member

I think the next step on this is probably to go through and surgically break some subtle things one at a time and make sure the test suite still catches it.

@armanbilge
Copy link
Member

Sorry, I snuck a new test in here.

Comment on lines 52 to 58
new ValueTransform(
"Other",
{
case r if !r.isInstanceOf[Unit] && !r.isInstanceOf[Prop] =>
sys.error(s"Unexpected value of type ${r.getClass.getName}: $r")
}
)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This transformer ensures the result type is Unit or Prop.
From the munit perspective, that's a valid test:

test("some test") {
  1 == 2
}

However, it should use assert:

test("some test") {
  assert(1 == 2)
}

Here are all the fixed tests that were exposed by this transformer: 9186d4b

@iRevive
Copy link
Contributor Author

iRevive commented Jan 3, 2025

Sorry, I snuck a new test in here.

No worries. I've backported the test.

@djspiewak
Copy link
Member

djspiewak commented Jan 3, 2025

So for some reason, IOAppSpec just hung for me locally. I ran root/testQuick and I think it was the native platform which hung:

[warn] Canceling execution...
[error] Test runner interrupted by fatal signal 2
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/example/native/target/scala-2.13/cats-effect-example-test-out finished with non-zero value 130 (0x82)
[error] Test runner interrupted by fatal signal 2
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/laws/native/target/scala-2.13/cats-effect-laws-test-out finished with non-zero value 130 (0x82)
[error] Test runner interrupted by fatal signal 2
[error] Test runner interrupted by fatal signal 2
[error] Test runner interrupted by fatal signal 2
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/tests/native/target/scala-2.13/cats-effect-tests-test-out finished with non-zero value 130 (0x82)
[error] Test runner interrupted by fatal signal 2
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/testkit/native/target/scala-2.13/cats-effect-testkit-test-out finished with non-zero value 130 (0x82)
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/tests/native/target/scala-2.13/cats-effect-tests-test-out finished with non-zero value 130 (0x82)
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/tests/native/target/scala-2.13/cats-effect-tests-test-out finished with non-zero value 130 (0x82)
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/kernel/native/target/scala-2.13/cats-effect-kernel-test-out finished with non-zero value 130 (0x82)
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/tests/native/target/scala-2.13/cats-effect-tests-test-out finished with non-zero value 130 (0x82)
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/tests/native/target/scala-2.13/cats-effect-tests-test-out finished with non-zero value 130 (0x82)
[error] Test runner interrupted by fatal signal 2
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/tests/native/target/scala-2.13/cats-effect-tests-test-out finished with non-zero value 130 (0x82)
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/tests/native/target/scala-2.13/cats-effect-tests-test-out finished with non-zero value 130 (0x82)
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/kernel-testkit/native/target/scala-2.13/cats-effect-kernel-testkit-test-out finished with non-zero value 130 (0x82)
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/std/native/target/scala-2.13/cats-effect-std-test-out finished with non-zero value 130 (0x82)
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/tests/native/target/scala-2.13/cats-effect-tests-test-out finished with non-zero value 130 (0x82)
[error] Test runner interrupted by fatal signal 2
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/tests/native/target/scala-2.13/cats-effect-tests-test-out finished with non-zero value 130 (0x82)
[error] Test runner interrupted by fatal signal 2
[error] Test runner interrupted by fatal signal 2
[error] Test runner interrupted by fatal signal 2
[error] Test runner interrupted by fatal signal 2
[error] Test runner interrupted by fatal signal 2
[error] Test runner interrupted by fatal signal 2
[error] Test runner interrupted by fatal signal 2
[error] Test runner interrupted by fatal signal 2
[error] Test runner interrupted by fatal signal 2
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/tests/native/target/scala-2.13/cats-effect-tests-test-out finished with non-zero value 130 (0x82)
[warn] Force close java.lang.RuntimeException: Process /Users/daniel/Development/Scala/cats-effect/series-3.x/core/native/target/scala-2.13/cats-effect-test-out finished with non-zero value 130 (0x82)
[info] cats.effect.IOAppSpec:
[error] ==> X cats.effect.IOAppSpec.evaluate and print hello world  0.159s munit.ComparisonFailException: /Users/daniel/Development/Scala/cats-effect/series-3.x/ioapp-tests/src/test/scala/IOAppSpec.scala:154
[error] 153:        val h = platform("HelloWorld", Nil)
[error] 154:        assertEquals(h.awaitStatus(), 0)
[error] 155:        assertEquals(h.stdout(), s"Hello, World!${System.lineSeparator()}")
[error] values are not the same
[error] => Obtained
[error] 1
[error] => Diff (- obtained, + expected)
[error] -1
[error] +0
[error]     at munit.Assertions.failComparison(Assertions.scala:274)
[error] ==> X cats.effect.IOAppSpec.pass all arguments to child  0.055s munit.ComparisonFailException: /Users/daniel/Development/Scala/cats-effect/series-3.x/ioapp-tests/src/test/scala/IOAppSpec.scala:161
[error] 160:        val h = platform("Arguments", expected)
[error] 161:        assertEquals(h.awaitStatus(), 0)
[error] 162:        assertEquals(
[error] values are not the same
[error] => Obtained
[error] 1
[error] => Diff (- obtained, + expected)
[error] -1
[error] +0
[error]     at munit.Assertions.failComparison(Assertions.scala:274)
[error] ==> X cats.effect.IOAppSpec.exit on non-fatal error  0.053s munit.FailException: /Users/daniel/Development/Scala/cats-effect/series-3.x/ioapp-tests/src/test/scala/IOAppSpec.scala:171 assertion failed
[error] 170:        assertEquals(h.awaitStatus(), 1)
[error] 171:        assert(h.stderr().contains("Boom!"))
[error] 172:      }
[error]     at munit.FunSuite.assert(FunSuite.scala:11)
[error]     at cats.effect.IOAppSpec.$anonfun$new$7(IOAppSpec.scala:171)
[error] ==> X cats.effect.IOAppSpec.exit with leaked fibers  0.059s munit.ComparisonFailException: /Users/daniel/Development/Scala/cats-effect/series-3.x/ioapp-tests/src/test/scala/IOAppSpec.scala:176
[error] 175:        val h = platform("LeakedFiber", List.empty)
[error] 176:        assertEquals(h.awaitStatus(), 0)
[error] 177:      }
[error] values are not the same
[error] => Obtained
[error] 1
[error] => Diff (- obtained, + expected)
[error] -1
[error] +0
[error]     at munit.Assertions.failComparison(Assertions.scala:274)
[error] ==> X cats.effect.IOAppSpec.exit on fatal error  0.055s munit.FailException: /Users/daniel/Development/Scala/cats-effect/series-3.x/ioapp-tests/src/test/scala/IOAppSpec.scala:182 assertion failed
[error] 181:        assertEquals(h.awaitStatus(), 1)
[error] 182:        assert(h.stderr().contains("Boom!"))
[error] 183:        assert(!h.stdout().contains("sadness"))
[error]     at munit.FunSuite.assert(FunSuite.scala:11)
[error]     at cats.effect.IOAppSpec.$anonfun$new$13(IOAppSpec.scala:182)
[error] ==> X cats.effect.IOAppSpec.exit on fatal error with other unsafe runs  0.059s munit.FailException: /Users/daniel/Development/Scala/cats-effect/series-3.x/ioapp-tests/src/test/scala/IOAppSpec.scala:189 assertion failed
[error] 188:        assertEquals(h.awaitStatus(), 1)
[error] 189:        assert(h.stderr().contains("Boom!"))
[error] 190:      }
[error]     at munit.FunSuite.assert(FunSuite.scala:11)
[error]     at cats.effect.IOAppSpec.$anonfun$new$19(IOAppSpec.scala:189)
[error] ==> X cats.effect.IOAppSpec.exit on raising a fatal error with attempt  0.045s munit.FailException: /Users/daniel/Development/Scala/cats-effect/series-3.x/ioapp-tests/src/test/scala/IOAppSpec.scala:195 assertion failed
[error] 194:        assertEquals(h.awaitStatus(), 1)
[error] 195:        assert(h.stderr().contains("Boom!"))
[error] 196:        assert(!h.stdout().contains("sadness"))
[error]     at munit.FunSuite.assert(FunSuite.scala:11)
[error]     at cats.effect.IOAppSpec.$anonfun$new$23(IOAppSpec.scala:195)
[error] ==> X cats.effect.IOAppSpec.exit on raising a fatal error with handleError  0.062s munit.FailException: /Users/daniel/Development/Scala/cats-effect/series-3.x/ioapp-tests/src/test/scala/IOAppSpec.scala:202 assertion failed
[error] 201:        assertEquals(h.awaitStatus(), 1)
[error] 202:        assert(h.stderr().contains("Boom!"))
[error] 203:        assert(!h.stdout().contains("sadness"))
[error]     at munit.FunSuite.assert(FunSuite.scala:11)
[error]     at cats.effect.IOAppSpec.$anonfun$new$29(IOAppSpec.scala:202)
[error] ==> X cats.effect.IOAppSpec.exit on raising a fatal error inside a map  0.044s munit.FailException: /Users/daniel/Development/Scala/cats-effect/series-3.x/ioapp-tests/src/test/scala/IOAppSpec.scala:209 assertion failed
[error] 208:        assertEquals(h.awaitStatus(), 1)
[error] 209:        assert(h.stderr().contains("Boom!"))
[error] 210:        assert(!h.stdout().contains("sadness"))
[error]     at munit.FunSuite.assert(FunSuite.scala:11)
[error]     at cats.effect.IOAppSpec.$anonfun$new$35(IOAppSpec.scala:209)
[error] ==> X cats.effect.IOAppSpec.exit on raising a fatal error inside a flatMap  0.056s munit.FailException: /Users/daniel/Development/Scala/cats-effect/series-3.x/ioapp-tests/src/test/scala/IOAppSpec.scala:216 assertion failed
[error] 215:        assertEquals(h.awaitStatus(), 1)
[error] 216:        assert(h.stderr().contains("Boom!"))
[error] 217:        assert(!h.stdout().contains("sadness"))
[error]     at munit.FunSuite.assert(FunSuite.scala:11)
[error]     at cats.effect.IOAppSpec.$anonfun$new$41(IOAppSpec.scala:216)
[error] ==> X cats.effect.IOAppSpec.warn on global runtime collision  0.046s munit.ComparisonFailException: /Users/daniel/Development/Scala/cats-effect/series-3.x/ioapp-tests/src/test/scala/IOAppSpec.scala:222
[error] 221:        val h = platform("GlobalRacingInit", List.empty)
[error] 222:        assertEquals(h.awaitStatus(), 0)
[error] 223:        assert(
[error] values are not the same
[error] => Obtained
[error] 1
[error] => Diff (- obtained, + expected)
[error] -1
[error] +0
[error]     at munit.Assertions.failComparison(Assertions.scala:274)
[error] ==> X cats.effect.IOAppSpec.reset global runtime on shutdown  0.097s munit.ComparisonFailException: /Users/daniel/Development/Scala/cats-effect/series-3.x/ioapp-tests/src/test/scala/IOAppSpec.scala:232
[error] 231:        val h = platform("GlobalShutdown", List.empty)
[error] 232:        assertEquals(h.awaitStatus(), 0)
[error] 233:        assert(
[error] values are not the same
[error] => Obtained
[error] 1
[error] => Diff (- obtained, + expected)
[error] -1
[error] +0
[error]     at munit.Assertions.failComparison(Assertions.scala:274)
[warn] ==> i cats.effect.IOAppSpec.warn on cpu starvation ignored 0.0s
[error] ==> X cats.effect.IOAppSpec.custom runtime installed as global  0.058s munit.ComparisonFailException: /Users/daniel/Development/Scala/cats-effect/series-3.x/ioapp-tests/src/test/scala/IOAppSpec.scala:258
[error] 257:        val h = platform("CustomRuntime", List.empty)
[error] 258:        assertEquals(h.awaitStatus(), 0)
[error] 259:      }
[error] values are not the same
[error] => Obtained
[error] 1
[error] => Diff (- obtained, + expected)
[error] -1
[error] +0
[error]     at munit.Assertions.failComparison(Assertions.scala:274)
[error] ==> X cats.effect.IOAppSpec.abort awaiting shutdown hooks  0.053s munit.ComparisonFailException: /Users/daniel/Development/Scala/cats-effect/series-3.x/ioapp-tests/src/test/scala/IOAppSpec.scala:264
[error] 263:          val h = platform("ShutdownHookImmediateTimeout", List.empty)
[error] 264:          assertEquals(h.awaitStatus(), 0)
[error] 265:        }
[error] values are not the same
[error] => Obtained
[error] 1
[error] => Diff (- obtained, + expected)
[error] -1
[error] +0
[error]     at munit.Assertions.failComparison(Assertions.scala:274)
[error] ==> X cats.effect.IOAppSpec.run finalizers on TERM  10.601s munit.ComparisonFailException: /Users/daniel/Development/Scala/cats-effect/series-3.x/ioapp-tests/src/test/scala/IOAppSpec.scala:301
[error] 300:        h.term()
[error] 301:        assertEquals(h.awaitStatus(), 143)
[error] 302:
[error] values are not the same
[error] => Obtained
[error] 1
[error] => Diff (- obtained, + expected)
[error] -1
[error] +143
[error]     at munit.Assertions.failComparison(Assertions.scala:274)
[info]   + exit on fatal error without IOApp 0.044s
[info]   + exit on canceled 0.055s
[error] ==> X cats.effect.IOAppSpec.live fiber snapshot  639.814s java.lang.InterruptedException: sleep interrupted
[error]     at java.lang.Thread.sleepNanos0(Native Method)
[error]     at java.lang.Thread.sleepNanos(Thread.java:496)
[error]     at java.lang.Thread.sleep(Thread.java:527)
[error]     at cats.effect.IOAppSpec.$anonfun$new$81(IOAppSpec.scala:331)
[error] ==> X cats.effect.IOAppSpec.gracefully ignore undefined process.exit  0.005s java.lang.InterruptedException: null
[error]     at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1696)
[error]     at java.lang.ProcessImpl.waitFor(ProcessImpl.java:425)
[error]     at scala.sys.process.ProcessImpl$SimpleProcess.exitValue(ProcessImpl.scala:266)
[error]     at cats.effect.IOAppSpec$Platform$$anon$1.awaitStatus(IOAppSpec.scala:49)
[error]     at cats.effect.IOAppSpec.$anonfun$new$105(IOAppSpec.scala:386)
Cancelled: testQuick

@iRevive
Copy link
Contributor Author

iRevive commented Jan 3, 2025

My best guess is that testQuick relies on the cached outputs. For example, testQuick doesn't even work on a fresh run:

...
[error] ==> X cats.effect.IOAppSpec.exit on canceled  0.002s java.io.IOException: Cannot run program "/Users/maksym/projects/oss/public/cats-effect/tests/native/target/scala-2.13/cats-effect-tests-out": error=2, No such file or directory
[error]     at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
[error]     at scala.sys.process.ProcessBuilderImpl$Simple.run(ProcessBuilderImpl.scala:85)
[error]     at cats.effect.IOAppSpec$Platform.apply(IOAppSpec.scala:42)
[error]     at cats.effect.IOAppSpec.$anonfun$new$79(IOAppSpec.scala:319)
[error] Caused by: java.io.IOException: error=2, No such file or directory
[error]     at java.lang.UNIXProcess.forkAndExec(Native Method)
[error]     at java.lang.UNIXProcess.<init>(UNIXProcess.java:247)
[error]     at java.lang.ProcessImpl.start(ProcessImpl.java:134)
[error]     at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
[error]     ... 4 more
[error] Failed: Total 16, Failed 16, Errors 0, Passed 0, Ignored 1

If you didn't clean the project, it may use the old cached native artifacts.

@djspiewak
Copy link
Member

For some reason, munit seems a lot more prone to hanging tests without timeouts in some failure cases. For example, if you remove the shouldFinalize() check on IOFiber.scala:700, you can reproduce tests hanging more or less indefinitely without any timeouts. I did a bunch of conditional flipping throughout the runtime and the most common result was just… hanging forever. It's not entirely clear to me why this would be the case, but obviously it would be much more ideal if the tests just timed out with a proper error.

@iRevive
Copy link
Contributor Author

iRevive commented Jan 9, 2025

I did some flipping tests before, and they were timing out correctly.
Turns out, they work fine on Java 21:

[info] welcome to sbt 1.10.7 (Azul Systems, Inc. Java 21.0.4)

sbt:cats-effect> testsJVM/testOnly *IOSuite
...
[error] ==> X cats.effect.IOSuite.random racing sleeps  20.004s java.util.concurrent.TimeoutException: test timed out after 20 seconds
[error] ==> X cats.effect.IOSuite.steal timers  20.005s java.util.concurrent.TimeoutException: test timed out after 20 seconds
[error] ==> X cats.effect.IOSuite.lots of externally-canceled timers  20.005s java.util.concurrent.TimeoutException: test timed out after 20 seconds
[info]   + not lose cedeing threads from the bypass when blocker transitioning 6.615s
[info]   + wake parked thread for polled events 1.307s
[error] ==> X cats.effect.IOSuite.block in-place on virtual threads  20.003s java.util.concurrent.TimeoutException: test timed out after 20 seconds
...

However, CPU usage skyrocketed to 1300%, and the fans went crazy.


Today I decided to use nix env, and the result was different:

[info] welcome to sbt 1.10.7 (Azul Systems, Inc. Java 1.8.0_422)

sbt:cats-effect> testsJVM/testOnly *IOSuite
...
[info]   + parTraverseN - throw when n < 1 0.003s
[info]   + parTraverseN - propagate errors 0.011s
...

Hangs forever. CPU usage is normal, though.

@djspiewak
Copy link
Member

Interesting. I'm on Java 23 and for me it was a forever hang with normal CPU.

@iRevive
Copy link
Contributor Author

iRevive commented Jan 9, 2025

Do you use Temurin by any chance?
Tested locally:

  • Eclipse Adoptium Java 21.0.4 - hangs
  • Azul Systems, Inc. Java 21.0.4 - times out correctly

I'm testing on Darwin Aarch64.

@djspiewak
Copy link
Member

openjdk 23.0.1 2024-10-15
OpenJDK Runtime Environment Temurin-23.0.1+11 (build 23.0.1+11)
OpenJDK 64-Bit Server VM Temurin-23.0.1+11 (build 23.0.1+11, mixed mode, sharing)

Fascinating! And somewhat terrifying. I wonder why there's such a significant difference between the distributions?

@iRevive
Copy link
Contributor Author

iRevive commented Jan 9, 2025

Seems to be related: scalameta/munit#730.
Once I switched to the global context from parasitic, the hanging was gone:

override def munitExecutionContext: ExecutionContext = ExecutionContext.global

@iRevive
Copy link
Contributor Author

iRevive commented Jan 10, 2025

I did some extra testing on the Azul JVM. After several reruns of the sbt test, it finally hung, too.

65dc9ad - this change fixes hanging behavior on all JVMs.

@djspiewak
Copy link
Member

This change still seems to hang forever for me:

diff --git a/core/shared/src/main/scala/cats/effect/IOFiber.scala b/core/shared/src/main/scala/cats/effect/IOFiber.scala
index 9e0357b734..39c44fd37e 100644
--- a/core/shared/src/main/scala/cats/effect/IOFiber.scala
+++ b/core/shared/src/main/scala/cats/effect/IOFiber.scala
@@ -697,7 +697,7 @@ private final class IOFiber[A](
                    */
                   suspend()
                 }
-              } else if (finalizing == state.wasFinalizing && !shouldFinalize() && outcome == null) {
+              } else if (finalizing == state.wasFinalizing && outcome == null) {
                 /*
                  * If we aren't canceled or completed, and we're
                  * still in the same finalization state, loop on

Maybe that's a unique one. I'm trying out a few more which hung previously.

@iRevive
Copy link
Contributor Author

iRevive commented Jan 11, 2025

This change still seems to hang forever for me:

diff --git a/core/shared/src/main/scala/cats/effect/IOFiber.scala b/core/shared/src/main/scala/cats/effect/IOFiber.scala
index 9e0357b734..39c44fd37e 100644
--- a/core/shared/src/main/scala/cats/effect/IOFiber.scala
+++ b/core/shared/src/main/scala/cats/effect/IOFiber.scala
@@ -697,7 +697,7 @@ private final class IOFiber[A](
                    */
                   suspend()
                 }
-              } else if (finalizing == state.wasFinalizing && !shouldFinalize() && outcome == null) {
+              } else if (finalizing == state.wasFinalizing && outcome == null) {
                 /*
                  * If we aren't canceled or completed, and we're
                  * still in the same finalization state, loop on

Maybe that's a unique one. I'm trying out a few more which hung previously.

Roughly 1 in 10 runs hangs, no matter what JVM you use.
I think I will have a gap next week to investigate this one properly.

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

Successfully merging this pull request may close these issues.

3 participants