In short cancelling one co-routine scope does not cancel other co-routine scopes. Other co-routines can continue to run, if they are not cancelled.

Code

package com.glassthought.sandbox
 
import gt.sandbox.util.output.Out
import kotlinx.coroutines.*
 
interface Server {
  suspend fun start()
  suspend fun stop()
  suspend fun join()
}
 
val out = Out.standard()
 
class ServerImpl(
  private val serverName: String,
  private val scope: CoroutineScope // Injected scope for better control
) : Server {
  private var backgroundJob: Job? = null
 
  override suspend fun start() {
    out.info("Starting server")
 
    backgroundJob = scope.launch(CoroutineName("${serverName}-work-1")) {
      out.info("Running server work in thread: ${Thread.currentThread().name}")
 
      launch {
        out.info("${serverName}: spawned from background job - work-A")
        delay(3000)
        out.info("${serverName}-work-A completed")
      }
 
      delay(2000)
      out.info("${serverName}-work-1 completed")
 
    }
  }
 
  override suspend fun stop() {
    out.info("Stopping server: $serverName")
 
    scope.cancel()
  }
 
  override suspend fun join() {
    if (backgroundJob != null) {
      backgroundJob!!.join()
    }
  }
}
 
fun main() = runBlocking {
  val server1 = ServerImpl("server-1", CoroutineScope(Dispatchers.Default))
  val server2 = ServerImpl("server-2", CoroutineScope(Dispatchers.Default))
 
  server1.start()
  server2.start()
 
  
  delay(10)
  // Stopping server 1 should not stop server - 2
  server1.stop()
 
  server1.join()
  server2.join()
  out.info("Main completed")
}

Command to reproduce:

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

Recorded output of command:

[elapsed:   39ms][🥇/tname:main/tid:1][coroutine:unnamed] Starting server
[elapsed:   57ms][🥇/tname:main/tid:1][coroutine:unnamed] Starting server
[elapsed:   57ms][⓶/tname:DefaultDispatcher-worker-1/tid:20][coroutine:server-1-work-1] Running server work in thread: DefaultDispatcher-worker-1
[elapsed:   57ms][⓷/tname:DefaultDispatcher-worker-2/tid:21][coroutine:server-2-work-1] Running server work in thread: DefaultDispatcher-worker-2
[elapsed:   59ms][⓸/tname:DefaultDispatcher-worker-3/tid:22][coroutine:server-1-work-1] server-1: spawned from background job - work-A
[elapsed:   59ms][⓹/tname:DefaultDispatcher-worker-4/tid:23][coroutine:server-2-work-1] server-2: spawned from background job - work-A
[elapsed:   71ms][🥇/tname:main/tid:1][coroutine:unnamed] Stopping server: server-1
[elapsed: 2065ms][⓷/tname:DefaultDispatcher-worker-2/tid:21][coroutine:server-2-work-1] server-2-work-1 completed
[elapsed: 3063ms][⓷/tname:DefaultDispatcher-worker-2/tid:21][coroutine:server-2-work-1] server-2-work-A completed
[elapsed: 3064ms][🥇/tname:main/tid:1][coroutine:unnamed] Main completed