Skip to content

Uncaught exception may not appear on console when main is waiting for a job #208

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

Closed
elizarov opened this issue Jan 23, 2018 · 4 comments
Closed

Comments

@elizarov
Copy link
Contributor

elizarov commented Jan 23, 2018

Consider the following code:

fun main(args: Array<String>) = runBlocking {
    val job = launch {
        doSomething()
    }
    job.join()
}

fun doSomething() {
    TODO("Not implemented")
}

Because of the order events are handled internally, main can wake up and terminate application before exception handler had a chance to print onto the console from its background thread.

Consider handling uncaught exceptions in launch before everything else.

@Starcarr
Copy link

This is still happening on 0.22 with Kotlin 1.2.21.

Code (same as the body of the issue)

fun main(args: Array<String>) = runBlocking {
    val job = launch {
        doSomething()
    }
    job.join()
}

fun doSomething() {
    TODO("Not implemented")
}

Sample output:

/usr/lib/jvm/java-8-openjdk/bin/java...
Process finished with exit code 0

@elizarov
Copy link
Contributor Author

Confirm. I've fixed the order in which invocations happen normally, but there is a problem in another place, too.

@elizarov elizarov reopened this Jan 25, 2018
@elizarov
Copy link
Contributor Author

Here is what I'm observing in this case:

  1. The job launches, executed and crashes even before the main coroutine reaches job.join statement.
  2. However, the OS scheduler resumes execution on the main thread before the crashed background thread has a change to print its error message on the console.
  3. Note, that by that time the state of the job is already complete (we update state first and the print exception on the console), so when main thread reaches join it does not even suspend, but goes straight though to the exit, terminates the process and does not leave any chance to the background thread to print its exception.

@elizarov
Copy link
Contributor Author

Fixed in version 0.22.1. Now, when launch Job starts to fail (completes with exception) it starts the process by transitioning into completing state, then it handles the exception (printing its stacktrace by default), then it becomes complete (allowing for a coroutine that is using join to go ahead).

elizarov added a commit that referenced this issue Sep 14, 2018
It is no longer needed, because handleJobException covers #208
elizarov added a commit that referenced this issue Sep 17, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Job.cancelChild(parent) is introduced as a dedicated method to
  send cancellation signal from parent to child.
* Job.getCancellationException() now works in completing state, too,
  and it is  used to get exception when parent's completion cancels
  children.
* Child never aggregates exception received from it parent.
* JobSupport.handleJobException() for launch/actor is split into:
  - cancelParentWithException - can be invoked multiple times on race;
  - handleJobException which - invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.
elizarov added a commit that referenced this issue Sep 18, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Job.cancelChild(parent) is introduced as a dedicated method to
  send cancellation signal from parent to child.
* Job.getCancellationException() now works in completing state, too,
  and it is  used to get exception when parent's completion cancels
  children.
* Child never aggregates exception received from it parent.
* JobSupport.handleJobException() for launch/actor is split into:
  - cancelParentWithException - can be invoked multiple times on race;
  - handleJobException which - invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.
elizarov added a commit that referenced this issue Sep 18, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Job.cancelChild(parent) is introduced as a dedicated method to
  send cancellation signal from parent to child.
* Job.getCancellationException() now works in completing state, too,
  and it is  used to get exception when parent's completion cancels
  children.
* Child never aggregates exception received from it parent.
* JobSupport.handleJobException() for launch/actor is split into:
  - cancelParentWithException - can be invoked multiple times on race;
  - handleJobException which - invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.
elizarov added a commit that referenced this issue Sep 19, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Job.cancelChild(parent) is introduced as a dedicated method to
  send cancellation signal from parent to child.
* Job.getCancellationException() now works in completing state, too,
  and it is  used to get exception when parent's completion cancels
  children.
* Child never aggregates exception received from it parent.
* JobSupport.handleJobException() for launch/actor is split into:
  - cancelParentWithException - can be invoked multiple times on race;
  - handleJobException which - invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.
elizarov added a commit that referenced this issue Sep 19, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Job.cancelChild(parent) is introduced as a dedicated method to
  send cancellation signal from parent to child.
* Job.getCancellationException() now works in completing state, too,
  and it is  used to get exception when parent's completion cancels
  children.
* Child never aggregates exception received from it parent.
* JobSupport.handleJobException() for launch/actor is split into:
  - cancelParentWithException - can be invoked multiple times on race;
  - handleJobException which - invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.
elizarov added a commit that referenced this issue Sep 19, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Job.cancelChild(parent) is introduced as a dedicated method to
  send cancellation signal from parent to child.
* Job.getCancellationException() now works in completing state, too,
  and it is  used to get exception when parent's completion cancels
  children.
* Child never aggregates exception received from it parent.
* JobSupport.handleJobException() for launch/actor is split into:
  - cancelParentWithException - can be invoked multiple times on race;
  - handleJobException which - invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.
elizarov added a commit that referenced this issue Sep 19, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Job.cancelChild(parent) is introduced as a dedicated method to
  send cancellation signal from parent to child.
* Job.getCancellationException() now works in completing state, too,
  and it is  used to get exception when parent's completion cancels
  children.
* Child never aggregates exception received from it parent.
* JobSupport.handleJobException() for launch/actor is split into:
  - cancelParentWithException - can be invoked multiple times on race;
  - handleJobException which - invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.
elizarov added a commit that referenced this issue Sep 19, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Consistent "Finishing" state was introduced in internal machinery:
  - Job enters finishing state when it is failing or it is completing
    and has children
  - Finishing state cleanly aggregates all failures, tracks cancellation
    and completion status
* Source-incompatible change: Job.invokeOnCompletion boolean parameter is
  change to onFailing. Such handlers are now invoked as soon as the job
  starts failing and the root cause exception of the failure is consistently
  passed to all the handlers.
* The following internal methods were introduced to facilitate this:
  - Job.failParent(exception) is used by child to signal failure to parent
  - Job.cancelChild(parentJob) is used by parent to cancel child.
* Child never aggregates exception received from it parent, but uses
  it as it root cause if there is no other exception.
* JobSupport.handleJobException() logic for launch/actor is split into:
  - failParent - can be invoked multiple times on race;
  - handleJobException which is invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.

Fixes #585
elizarov added a commit that referenced this issue Sep 19, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Consistent "Finishing" state was introduced in internal machinery:
  - Job enters finishing state when it is failing or it is completing
    and has children
  - Finishing state cleanly aggregates all failures, tracks cancellation
    and completion status
* Source-incompatible change: Job.invokeOnCompletion boolean parameter is
  change to onFailing. Such handlers are now invoked as soon as the job
  starts failing and the root cause exception of the failure is consistently
  passed to all the handlers.
* The following internal methods were introduced to facilitate this:
  - Job.failParent(exception) is used by child to signal failure to parent
  - Job.cancelChild(parentJob) is used by parent to cancel child.
* Child never aggregates exception received from it parent, but uses
  it as it root cause if there is no other exception.
* JobSupport.handleJobException() logic for launch/actor is split into:
  - failParent - can be invoked multiple times on race;
  - handleJobException which is invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.

Fixes #585
elizarov added a commit that referenced this issue Sep 20, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Consistent "Finishing" state was introduced in internal machinery:
  - Job enters finishing state when it is failing or it is completing
    and has children
  - Finishing state cleanly aggregates all failures, tracks cancellation
    and completion status
* Job.isFailed is introduced as a consistent way to query the "failing"
  state of the job that was previously only implicitly available via
  invokeOnCompletion handler (cause != null means a failed job) and
  the documentation for both Job & Deferred is updated to reflect that.
* Source-incompatible change: Job.invokeOnCompletion boolean parameter is
  change to onFailing. Such handlers are now invoked as soon as the job
  starts failing and the root cause exception of the failure is consistently
  passed to all the handlers.
* The following internal methods were introduced to facilitate this:
  - Job.failParent(exception) is used by child to signal failure to parent
  - Job.cancelChild(parentJob) is used by parent to cancel child.
* Child never aggregates exception received from it parent, but uses
  it as it root cause if there is no other exception.
* JobSupport.handleJobException() logic for launch/actor is split into:
  - failParent - can be invoked multiple times on race;
  - handleJobException which is invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.

Fixes #585
elizarov added a commit that referenced this issue Sep 20, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Consistent "Finishing" state was introduced in internal machinery:
  - Job enters finishing state when it is failing or it is completing
    and has children
  - Finishing state cleanly aggregates all failures, tracks cancellation
    and completion status
* Job.isFailed is introduced as a consistent way to query the "failing"
  state of the job that was previously only implicitly available via
  invokeOnCompletion handler (cause != null means a failed job) and
  the documentation for both Job & Deferred is updated to reflect that.
* Source-incompatible change: Job.invokeOnCompletion boolean parameter is
  change to onFailing. Such handlers are now invoked as soon as the job
  starts failing and the root cause exception of the failure is consistently
  passed to all the handlers.
* The following internal methods were introduced to facilitate this:
  - Job.failParent(exception) is used by child to signal failure to parent
  - Job.cancelChild(parentJob) is used by parent to cancel child.
* Child never aggregates exception received from it parent, but uses
  it as it root cause if there is no other exception.
* JobSupport.handleJobException() logic for launch/actor is split into:
  - failParent - can be invoked multiple times on race;
  - handleJobException which is invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.

Fixes #585
elizarov added a commit that referenced this issue Sep 20, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Consistent "Finishing" state was introduced in internal machinery:
  - Job enters finishing state when it is failing or it is completing
    and has children
  - Finishing state cleanly aggregates all failures, tracks cancellation
    and completion status
* Job.isFailed is introduced as a consistent way to query the "failing"
  state of the job that was previously only implicitly available via
  invokeOnCompletion handler (cause != null means a failed job) and
  the documentation for both Job & Deferred is updated to reflect that.
* Source-incompatible change: Job.invokeOnCompletion boolean parameter is
  change to onFailing. Such handlers are now invoked as soon as the job
  starts failing and the root cause exception of the failure is consistently
  passed to all the handlers.
* The following internal methods were introduced to facilitate this:
  - Job.failParent(exception) is used by child to signal failure to parent
  - Job.cancelChild(parentJob) is used by parent to cancel child.
* Child never aggregates exception received from it parent, but uses
  it as it root cause if there is no other exception.
* JobSupport.handleJobException() logic for launch/actor is split into:
  - failParent - can be invoked multiple times on race;
  - handleJobException which is invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.

Fixes #585
elizarov added a commit that referenced this issue Sep 20, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Consistent "Finishing" state was introduced in internal machinery:
  - Job enters finishing state when it is failing or it is completing
    and has children
  - Finishing state cleanly aggregates all failures, tracks cancellation
    and completion status
* Job.isFailed is introduced as a consistent way to query the "failing"
  state of the job that was previously only implicitly available via
  invokeOnCompletion handler (cause != null means a failed job) and
  the documentation for both Job & Deferred is updated to reflect that.
* Source-incompatible change: Job.invokeOnCompletion boolean parameter is
  change to onFailing. Such handlers are now invoked as soon as the job
  starts failing and the root cause exception of the failure is consistently
  passed to all the handlers.
* The following internal methods were introduced to facilitate this:
  - Job.failParent(exception) is used by child to signal failure to parent
  - Job.cancelChild(parentJob) is used by parent to cancel child.
* Child never aggregates exception received from it parent, but uses
  it as it root cause if there is no other exception.
* JobSupport.handleJobException() logic for launch/actor is split into:
  - failParent - can be invoked multiple times on race;
  - handleJobException which is invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.

Fixes #585
elizarov added a commit that referenced this issue Sep 20, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Consistent "Finishing" state was introduced in internal machinery:
  - Job enters finishing state when it is failing or it is completing
    and has children
  - Finishing state cleanly aggregates all failures, tracks cancellation
    and completion status
* Job.isFailed is introduced as a consistent way to query the "failing"
  state of the job that was previously only implicitly available via
  invokeOnCompletion handler (cause != null means a failed job) and
  the documentation for both Job & Deferred is updated to reflect that.
* Source-incompatible change: Job.invokeOnCompletion boolean parameter is
  change to onFailing. Such handlers are now invoked as soon as the job
  starts failing and the root cause exception of the failure is consistently
  passed to all the handlers.
* The following internal methods were introduced to facilitate this:
  - Job.failParent(exception) is used by child to signal failure to parent
  - Job.cancelChild(parentJob) is used by parent to cancel child.
* Child never aggregates exception received from it parent, but uses
  it as it root cause if there is no other exception.
* JobSupport.handleJobException() logic for launch/actor is split into:
  - failParent - can be invoked multiple times on race;
  - handleJobException which is invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.

Fixes #585
elizarov added a commit that referenced this issue Sep 20, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Consistent "Finishing" state was introduced in internal machinery:
  - Job enters finishing state when it is failing or it is completing
    and has children
  - Finishing state cleanly aggregates all failures, tracks cancellation
    and completion status
* Job.isFailed is introduced as a consistent way to query the "failing"
  state of the job that was previously only implicitly available via
  invokeOnCompletion handler (cause != null means a failed job) and
  the documentation for both Job & Deferred is updated to reflect that.
* Source-incompatible change: Job.invokeOnCompletion boolean parameter is
  change to onFailing. Such handlers are now invoked as soon as the job
  starts failing and the root cause exception of the failure is consistently
  passed to all the handlers.
* The following internal methods were introduced to facilitate this:
  - Job.failParent(exception) is used by child to signal failure to parent
  - Job.cancelChild(parentJob) is used by parent to cancel child.
* Child never aggregates exception received from it parent, but uses
  it as it root cause if there is no other exception.
* JobSupport.handleJobException() logic for launch/actor is split into:
  - failParent - can be invoked multiple times on race;
  - handleJobException which is invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.

Fixes #585
elizarov added a commit that referenced this issue Sep 21, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Consistent "Finishing" state was introduced in internal machinery:
  - Job enters finishing state when it is failing or it is completing
    and has children
  - Finishing state cleanly aggregates all failures, tracks cancellation
    and completion status
* Job.isFailed is introduced as a consistent way to query the "failing"
  state of the job that was previously only implicitly available via
  invokeOnCompletion handler (cause != null means a failed job) and
  the documentation for both Job & Deferred is updated to reflect that.
* Source-incompatible change: Job.invokeOnCompletion boolean parameter is
  change to onFailing. Such handlers are now invoked as soon as the job
  starts failing and the root cause exception of the failure is consistently
  passed to all the handlers.
* The following internal methods were introduced to facilitate this:
  - Job.failParent(exception) is used by child to signal failure to parent
  - Job.cancelChild(parentJob) is used by parent to cancel child.
* Child never aggregates exception received from it parent, but uses
  it as it root cause if there is no other exception.
* JobSupport.handleJobException() logic for launch/actor is split into:
  - failParent - can be invoked multiple times on race;
  - handleJobException which is invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.

Fixes #585
elizarov added a commit that referenced this issue Sep 23, 2018
* Removed legacy onFinishing handler support from JobSupport.
  - It is no longer needed, because handleJobException covers #208
* Fixed bugs that were masked by cancelling parent from onFinishing.
* Consistent "Finishing" state was introduced in internal machinery:
  - Job enters finishing state when it is failing or it is completing
    and has children
  - Finishing state cleanly aggregates all failures, tracks cancellation
    and completion status
* Job.isFailed is introduced as a consistent way to query the "failing"
  state of the job that was previously only implicitly available via
  invokeOnCompletion handler (cause != null means a failed job) and
  the documentation for both Job & Deferred is updated to reflect that.
* Source-incompatible change: Job.invokeOnCompletion boolean parameter is
  change to onFailing. Such handlers are now invoked as soon as the job
  starts failing and the root cause exception of the failure is consistently
  passed to all the handlers.
* The following internal methods were introduced to facilitate this:
  - Job.failParent(exception) is used by child to signal failure to parent
  - Job.cancelChild(parentJob) is used by parent to cancel child.
* Child never aggregates exception received from it parent, but uses
  it as it root cause if there is no other exception.
* JobSupport.handleJobException() logic for launch/actor is split into:
  - failParent - can be invoked multiple times on race;
  - handleJobException which is invoked exactly once.
* Exception materiazization is much lazier now, which should
  significantly improve performance when cancelling large hierarchies.
* Other minor perf improvements in JobSupport code.

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

No branches or pull requests

2 participants