title: Coroutine StateFlow stops emitting when CoroutineScope is cancelled
body: <p>I have a <code>StateFlow</code> coroutine that is shared amongst various parts of my application. When I <code>cancel</code> the <code>CoroutineScope</code> of a downstream collector, a <code>JobCancellationException</code> is propagated up to the <code>StateFlow</code>, and it stops emitting values for all current and future collectors.</p>
  <p>The <code>StateFlow</code>:</p>
  <pre><code>val songsRelay: Flow&lt;List&lt;Song&gt;&gt; by lazy {
      MutableStateFlow&lt;List&lt;Song&gt;?&gt;(null).apply {
          CoroutineScope(Dispatchers.IO)
              .launch { songDataDao.getAll().distinctUntilChanged().collect { value = it } }
      }.filterNotNull()
  }
  </code></pre>
  <p>A typical 'presenter' in my code implements the following base class:</p>
  <pre><code>abstract class BasePresenter&lt;T : Any&gt; : BaseContract.Presenter&lt;T&gt; {
  
      var view: T? = null
  
      private val job by lazy {
          Job()
      }
  
      private val coroutineScope by lazy { CoroutineScope( job + Dispatchers.Main) }
  
      override fun bindView(view: T) {
          this.view = view
      }
  
      override fun unbindView() {
          job.cancel()
          view = null
      }
  
      fun launch(block: suspend CoroutineScope.() -&gt; Unit): Job {
          return coroutineScope.launch(block = block)
      }
  }
  </code></pre>
  <p>A <code>BasePresenter</code> implementation might call <code>launch{ songsRelay.collect {...} }</code>
  When the presenter is unbound, in order to prevent leaks, I cancel the parent job. Any time a presenter that was collecting the <code>songsRelay</code> <code>StateFlow</code> is unbound, the <code>StateFlow</code> is essentially terminated with a <code>JobCancellationException</code>, and no other collectors/presenters can collect values from it.</p>
  <p>I've noticed that I can call <code>job.cancelChildren()</code> instead, and this seems to work (<code>StateFlow</code> doesn't complete with a <code>JobCancellationException</code>). But then I wonder what the point is of declaring a parent <code>job</code>, if I can't cancel the job itself. I could just remove <code>job</code> altogether, and call <code>coroutineScope.coroutineContext.cancelChildren()</code> to the same effect.</p>
  <p>If I do just call <code>job.cancelChildren()</code>, is that sufficient? I feel like by not calling <code>coroutineScope.cancel()</code>, or <code>job.cancel()</code>, I may not be correctly or completely cleaning up the tasks that I have kicked off.</p>
  <p>I also don't understand why the <code>JobCancellationException</code> is propagated up the hierarchy when <code>job.cancel()</code> is called. Isn't <code>job</code> the 'parent' here? Why does cancelling it affect my <code>StateFlow</code>?</p>