Control.Exception.bracket is broken(?)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Control.Exception.bracket is broken(?)

Yuras Shumovich
Hello,

From docs: "If an exception is raised, then bracket will re-raise the
exception (after performing the release)."

But what if the release action will throw an exception? There are 3
options:
 1) suppress the exception from release action and rethrow the original
one
 2) shutdown the program
 3) suppress the original exception and throw the exception from release
action.

Current behavior is #3 -- suppress the original exception. I think it
the worse choice.

What other languages do:

 - java has try-with-resources statement which is the nearest equivalent
of haskell's "bracket". It uses the option #1 (rethrow the original
exception)

 - in c++ it is common to use RAII for resource management, so someone's
destructor performs resource cleanup. But if destructor throws exception
during stack unrolling, the program is terminated (option #2)

I prefer #2 because suppressing exception is a really bad idea. What is
your choice?

And the related thing. Release action should not use any interruptible
action. Otherwise async exception can occur while processing other
exception, so one of them will be suppressed. Is it correct?
Control.Exception module contains a list of uninterruptible actions (see
"Interruptible operations" section), and e.g. "hClose" is not there. Is
"hClose" interruptible or not? If async exception interrupts "hClose",
the file descriptor will leak. So, should we use uninterruptibleMask in
release action for "bracket"?

Thanks,
Yuras

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Control.Exception.bracket is broken(?)

Mike Meyer


On Jul 6, 2014 8:15 AM, "Yuras Shumovich" <[hidden email]> wrote:
>
> Hello,
>
> From docs: "If an exception is raised, then bracket will re-raise the
> exception (after performing the release)."
>
> But what if the release action will throw an exception? There are 3
> options:
>  1) suppress the exception from release action and rethrow the original
> one
>  2) shutdown the program
>  3) suppress the original exception and throw the exception from release
> action.
>
> Current behavior is #3 -- suppress the original exception. I think it
> the worse choice.
>
> What other languages do:
>
>  - java has try-with-resources statement which is the nearest equivalent
> of haskell's "bracket". It uses the option #1 (rethrow the original
> exception)
>
>  - in c++ it is common to use RAII for resource management, so someone's
> destructor performs resource cleanup. But if destructor throws exception
> during stack unrolling, the program is terminated (option #2)

You left off what I think is the best behavior, from Python 3:

4) Throw the exception for the release action, chaining the original exception to it. The default exception handler reports the them both.

> I prefer #2 because suppressing exception is a really bad idea. What is
> your choice?

#4.


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Control.Exception.bracket is broken(?)

Yuras Shumovich
On Sun, 2014-07-06 at 08:37 -0500, Mike Meyer wrote:
> You left off what I think is the best behavior, from Python 3:
>
> 4) Throw the exception for the release action, chaining the original
> exception to it. The default exception handler reports the them both.

You mean the "__context__" attribute of the exception? Java also allows
one to get the suppressed exception via "Throwable.getSuppressed"
method. But python3 suppresses the original exception, while java does
the opposite, so I'm ok to count it as a separate option (#4). Thanks.

>
> > I prefer #2 because suppressing exception is a really bad idea. What is
> > your choice?
>
> #4.

Is it common for python3 code to be prepared to handle __context__? I
guess most developers just ignore it. So probably #1 is better?


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Control.Exception.bracket is broken(?)

Mike Meyer
On Sun, Jul 6, 2014 at 9:16 AM, Yuras Shumovich <[hidden email]> wrote:
On Sun, 2014-07-06 at 08:37 -0500, Mike Meyer wrote:
> You left off what I think is the best behavior, from Python 3:
>
> 4) Throw the exception for the release action, chaining the original
> exception to it. The default exception handler reports the them both.

You mean the "__context__" attribute of the exception? Java also allows
one to get the suppressed exception via "Throwable.getSuppressed"
method. But python3 suppresses the original exception, while java does
the opposite, so I'm ok to count it as a separate option (#4). Thanks.

>
> > I prefer #2 because suppressing exception is a really bad idea. What is
> > your choice?
>
> #4.

Is it common for python3 code to be prepared to handle __context__? I
guess most developers just ignore it. So probably #1 is better?

There are two types of exception handles in most Python applications. Ones that handle specific exceptions should catch as few exceptions as possible. These are narrowed to include as little code as possible, and only catch the exceptions they know how to deal with. They normally won't deal with __context__ unless they expect to catch such exceptions.

The other type is a catchall handler that usually tries to report the exception and return the application to a known state. It should handle __context__.

Personally, I think that #2 is a really bad option, because it makes it impossible to properly write exception handlers of the second type. While I understand the urge - my usual such handler for long-running programs is to exec itself to create a clean instance -  you should still make that option available to the programmer.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Control.Exception.bracket is broken(?)

Niklas Hambüchen
In reply to this post by Yuras Shumovich
On 06/07/14 14:15, Yuras Shumovich wrote:
> And the related thing. Release action should not use any interruptible
> action. Otherwise async exception can occur while processing other
> exception, so one of them will be suppressed. Is it correct?
> Control.Exception module contains a list of uninterruptible actions (see
> "Interruptible operations" section), and e.g. "hClose" is not there. Is
> "hClose" interruptible or not? If async exception interrupts "hClose",
> the file descriptor will leak. So, should we use uninterruptibleMask in
> release action for "bracket"?

Does anybody know the answer to these questions, especially the first one?
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe