Let me just start by saying this is not about NonFatal, I think the exceptions that NonFatal does and doesn't consider fatal are fine. This is about whether the Future API should use NonFatal.
The problem is, why should Futures force a policy of what exceptions are considered fatal and what aren't on consumers of it's API? If it didn't do this, then consumers would have to do this:future.onFailure {case NonFatal(e) => ...}Thus making that decision for themselves. The above is not only terse, it is also idiomatic, it matches what the consumer would do for an ordinary try catch. But the Scala future API doesn't allow the user to decide which exceptions are fatal and which aren't, because in all its exception handling, it only catches NonFatal.
On Mon, Jan 28, 2013 at 1:13 AM, James Roper <jro...@gmail.com> wrote:
Let me just start by saying this is not about NonFatal, I think the exceptions that NonFatal does and doesn't consider fatal are fine. This is about whether the Future API should use NonFatal.The problem is, why should Futures force a policy of what exceptions are considered fatal and what aren't on consumers of it's API? If it didn't do this, then consumers would have to do this:future.onFailure {case NonFatal(e) => ...}Thus making that decision for themselves. The above is not only terse, it is also idiomatic, it matches what the consumer would do for an ordinary try catch. But the Scala future API doesn't allow the user to decide which exceptions are fatal and which aren't, because in all its exception handling, it only catches NonFatal.Future and Try are indeed pretty opinionated on this matter. Abstracting over this would complicate the API; catching `_: Throwable` brings different set of problems, most notably masking platform errors like OutOfMemoryError by translating them into 'user' errors.
If you control the construction of the futures, you could go for something like:case class DevError(cause: Throwable) extends RuntimeException(cause)@inline def allowingDevErrors[A](a: => A) {if (isDevMode) try a catch { case ex @ (_: NotImplementedError | _: LinkageError) => throw DevError(ex)else a}future { allowingDevErrors( ... ) }Would that pattern help you out at all?-jason
--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group, send email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
I think the point is that this can go horribly wrong if people are not aware of the requirements, especially with ControlThrowable.
If the issues with using a user-catchable exception for control flow could be fixed, imho a change could alt least be considered, but in the current situation ...
--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group, send email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Future and Try are indeed pretty opinionated on this matter. Abstracting over this would complicate the API; catching `_: Throwable` brings different set of problems, most notably masking platform errors like OutOfMemoryError by translating them into 'user' errors.
On Mon, Jan 28, 2013 at 1:13 AM, James Roper <jro...@gmail.com> wrote:Let me just start by saying this is not about NonFatal, I think the exceptions that NonFatal does and doesn't consider fatal are fine. This is about whether the Future API should use NonFatal.The problem is, why should Futures force a policy of what exceptions are considered fatal and what aren't on consumers of it's API? If it didn't do this, then consumers would have to do this:future.onFailure {case NonFatal(e) => ...}Thus making that decision for themselves. The above is not only terse, it is also idiomatic, it matches what the consumer would do for an ordinary try catch. But the Scala future API doesn't allow the user to decide which exceptions are fatal and which aren't, because in all its exception handling, it only catches NonFatal.Future and Try are indeed pretty opinionated on this matter. Abstracting over this would complicate the API; catching `_: Throwable` brings different set of problems, most notably masking platform errors like OutOfMemoryError by translating them into 'user' errors.
On Tuesday, 29 January 2013 00:50:28 UTC+11, Jason Zaugg wrote:On Mon, Jan 28, 2013 at 1:13 AM, James Roper <jro...@gmail.com> wrote:
Let me just start by saying this is not about NonFatal, I think the exceptions that NonFatal does and doesn't consider fatal are fine. This is about whether the Future API should use NonFatal.The problem is, why should Futures force a policy of what exceptions are considered fatal and what aren't on consumers of it's API? If it didn't do this, then consumers would have to do this:future.onFailure {case NonFatal(e) => ...}Thus making that decision for themselves. The above is not only terse, it is also idiomatic, it matches what the consumer would do for an ordinary try catch. But the Scala future API doesn't allow the user to decide which exceptions are fatal and which aren't, because in all its exception handling, it only catches NonFatal.Future and Try are indeed pretty opinionated on this matter. Abstracting over this would complicate the API; catching `_: Throwable` brings different set of problems, most notably masking platform errors like OutOfMemoryError by translating them into 'user' errors.OOME is always a funny one, it usually is a user error, but handling it can be very dangerous (ie, can exacerbate the problem, can cause the JVM to just hang, etc). One way to deal with this is to have an oome parachute, ie, hold a memory buffer somewhere that you release when you encounter an OOME, and hope that that's going to give you enough heap space, and that you'll get to it first, to be able to handle the error. But that's probably overkill for this situation. But StackOverflowError is similarly dangerous to handle, since handling it may produce another StackOverflowError (as we've seen recently with futures), yet futures still try to handle that. Another one is ThreadDeath, which if handled, must always be rethrown. UnknownError is probably also not a good idea to handle.
But I definitely think LinkageError and NotImplementedError are safe for futures to handle -
you're not going to encounter them in a running production system, that is, you'll only encounter them soon after the production system starts up. You could encounter them if you were doing dynamic class loading, but in that case you probably also want to handle them.
If you control the construction of the futures, you could go for something like:case class DevError(cause: Throwable) extends RuntimeException(cause)@inline def allowingDevErrors[A](a: => A) {if (isDevMode) try a catch { case ex @ (_: NotImplementedError | _: LinkageError) => throw DevError(ex)else a}future { allowingDevErrors( ... ) }Would that pattern help you out at all?-jason
--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
On Mon, Jan 28, 2013 at 10:51 PM, James Roper <jro...@gmail.com> wrote:
On Tuesday, 29 January 2013 00:50:28 UTC+11, Jason Zaugg wrote:On Mon, Jan 28, 2013 at 1:13 AM, James Roper <jro...@gmail.com> wrote:
Let me just start by saying this is not about NonFatal, I think the exceptions that NonFatal does and doesn't consider fatal are fine. This is about whether the Future API should use NonFatal.The problem is, why should Futures force a policy of what exceptions are considered fatal and what aren't on consumers of it's API? If it didn't do this, then consumers would have to do this:future.onFailure {case NonFatal(e) => ...}Thus making that decision for themselves. The above is not only terse, it is also idiomatic, it matches what the consumer would do for an ordinary try catch. But the Scala future API doesn't allow the user to decide which exceptions are fatal and which aren't, because in all its exception handling, it only catches NonFatal.Future and Try are indeed pretty opinionated on this matter. Abstracting over this would complicate the API; catching `_: Throwable` brings different set of problems, most notably masking platform errors like OutOfMemoryError by translating them into 'user' errors.OOME is always a funny one, it usually is a user error, but handling it can be very dangerous (ie, can exacerbate the problem, can cause the JVM to just hang, etc). One way to deal with this is to have an oome parachute, ie, hold a memory buffer somewhere that you release when you encounter an OOME, and hope that that's going to give you enough heap space, and that you'll get to it first, to be able to handle the error. But that's probably overkill for this situation. But StackOverflowError is similarly dangerous to handle, since handling it may produce another StackOverflowError (as we've seen recently with futures), yet futures still try to handle that. Another one is ThreadDeath, which if handled, must always be rethrown. UnknownError is probably also not a good idea to handle.Yes. StackOverflowError isn't considered Fatal though.But I definitely think LinkageError and NotImplementedError are safe for futures to handle -I disagree wrt LinkageError – check direct subclasses of LinkageError: http://docs.oracle.com/javase/7/docs/api/java/lang/LinkageError.htmlyou're not going to encounter them in a running production system, that is, you'll only encounter them soon after the production system starts up. You could encounter them if you were doing dynamic class loading, but in that case you probably also want to handle them.The only things here which I think are not necessarily fatal are NotImplementedError and ControlThrowable. So I could argue that they should be removed from there.
I think the current NonFatal conflates 2 distinctly different things:
1) Throwables that are to be considered _fatal_ i.e. that the program needs termination2) Throwables that user code is not intended to catchI propose to split out number 2 into a different entity called ``Catchable`` or otherwise, and review where NonFatal is currently used in a "flawed" way.
--
-jason
... you're not suggesting that the inclusion of Try wasn't fully thought out, are you?
Well, right now it's actually silently broken for NotImplementedError and for ControlThrowable.
def apply(t: Throwable): Boolean = t match {case _: InterruptedException _: ControlThrowable | _: NotImplementedError => falsecase _ => NonFatal(t)}
-jason
--
Why not make it configurable? For instance every method that matches on NonFatal could allow the extractor to be passed implicitly.
(a) The subject -- it would be a way to allow individuals to decide, or include additional exceptions(b) Backward compatibility -- it would allow to fix the default implementation while allowing people relying on the existing behavior to keep it(c) Differences of opinion -- if there are any exceptions that are not black-and-white in one category or the other, it would allow it to be configured.
I wasn't responding specifically to that. Can you clarify what the issue is?