⚠️ join() does NOT rethrow ⚠️

Unlike await() which does rethrow, join() just waits for co-routine to complete, without care of whether completion was successful or failure.

⚠️ join() does NOT rethrow code example ⚠️

Code

package com.glassthought.sandbox

import gt.sandbox.util.output.Emojis
import gt.sandbox.util.output.Out
import kotlinx.coroutines.*
import kotlin.system.exitProcess
import kotlin.time.Duration.Companion.milliseconds

fun main(): Unit = runBlocking {
  val out = Out.standard()
  out.info("START")

  try {
    mainImpl(out)
  } catch (e: Exception) {
    out.error("in main got an exception! of type=[${e::class.simpleName}] with msg=[${e.message}] cause=[${e.cause}]. Exiting with error code 1")

    exitProcess(1)
  }

  out.info("DONE - WITHOUT errors on main")
}

private suspend fun mainImpl(out: Out) {
  val parentJob = Job()
  val scope = CoroutineScope(parentJob)

  out.info("Launching coroutine that will throw exception...")
  val job = scope.launch {
    out.info("Launch coroutine started")

    out.delayLogsCancellation(500.milliseconds)

    throw MyExceptionWillThrowFromCoroutine.create("Exception from launch", out)
  }

  out.actionWithMsg("job.join()", { job.join() })
  out.infoPrintState(job, "launchJob")
  out.infoPrintState(scope, "scope-where-we-launched")
}

class MyExceptionWillThrowFromCoroutine private constructor(msg: String) : RuntimeException(msg) {
  companion object {
    suspend fun create(msg: String, out: Out): MyExceptionWillThrowFromCoroutine {
      val exc = MyExceptionWillThrowFromCoroutine(msg)

      out.warn("${Emojis.EXCEPTOIN} throwing exception=[${exc::class.simpleName}] with msg=[${msg}]")

      return exc
    }
  }
}

Command to reproduce:

gt.sandbox.checkout.commit 73693c5d8d2ddb27f9a7 \
&& cd "${GT_SANDBOX_REPO}" \
&& cmd.run.announce "./gradlew run --quiet"

Recorded output of command:

Picked up JAVA_TOOL_OPTIONS: -Dkotlinx.coroutines.debug
Picked up JAVA_TOOL_OPTIONS: -Dkotlinx.coroutines.debug
[INFO][elapsed:   14ms][🥇][①][coroutname:@coroutine#1][tname:main/tid:1] START
[INFO][elapsed:   29ms][🥇][①][coroutname:@coroutine#1][tname:main/tid:1] Launching coroutine that will throw exception...
[INFO][elapsed:   34ms][2️⃣][⓶][coroutname:@coroutine#2][tname:DefaultDispatcher-worker-1/tid:31] Launch coroutine started
[INFO][elapsed:   34ms][🥇][①][coroutname:@coroutine#1][tname:main/tid:1] Performing action=[job.join()]
[WARN][elapsed:  569ms][2️⃣][⓶][coroutname:@coroutine#2][tname:DefaultDispatcher-worker-1/tid:31] 💥  throwing exception=[MyExceptionWillThrowFromCoroutine] with msg=[Exception from launch]
Exception in thread "DefaultDispatcher-worker-1 @coroutine#2" com.glassthought.sandbox.MyExceptionWillThrowFromCoroutine: Exception from launch
	at com.glassthought.sandbox.MyExceptionWillThrowFromCoroutine$Companion.create(Main.kt:46)
	at com.glassthought.sandbox.MainKt$mainImpl$job$1.invokeSuspend(Main.kt:34)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [CoroutineId(2), "coroutine#2":StandaloneCoroutine{Cancelling}@e541635, Dispatchers.Default]
[INFO][elapsed:  576ms][🥇][①][coroutname:@coroutine#1][tname:main/tid:1] Performed action=[job.join()]
[INFO][elapsed:  579ms][🥇][①][coroutname:@coroutine#1][tname:main/tid:1] State of [launchJob]:
launchJob.isActive    | false
launchJob.isCancelled | true
launchJob.isCompleted | true
[INFO][elapsed:  579ms][🥇][①][coroutname:@coroutine#1][tname:main/tid:1] State of [scope-where-we-launched]: isActive=false
[INFO][elapsed:  580ms][🥇][①][coroutname:@coroutine#1][tname:main/tid:1] DONE - WITHOUT errors on main

Backlinks