March 14, 2012

On 3/12/2012 7:07 PM, Sean Kelly wrote:
> On Mar 12, 2012, at 5:35 PM, Walter Bright<walter@digitalmars.com>  wrote:
>
>>
>> On 3/12/2012 2:39 PM, Sean Kelly wrote:
>>> On Mar 12, 2012, at 2:30 PM, Walter Bright wrote:
>>>> On 3/12/2012 12:34 PM, Sean Kelly wrote:
>>>>> I'm on the fence about whether attempting cleanup when an Error is thrown is desired behavior.  If there is no cleanup, why allow Errors to be caught at all?  We may as well simply call abort() at the point they're thrown.
>>>>>
>>>> So that an informative message can be printed, the backup engaged, attempt to shut down gracefully, log the failure details to a file, etc.
>>> … none of which may work if scope(exit) calls weren't run when the stack was unwound, since acquired mutexes would still be locked, etc.  I'd feel a lot less safe with having effectively done a longjmp across code that normally assumes finalization than with whatever the cause of the assertion did in the first place.
>>>
>> It's understood it may not work.
> So what's the reason to not call finalizers?
>

The program is corrupted at that point. The less code one attempts to run, the better.
_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals
March 14, 2012

On 3/14/2012 4:13 PM, Jesse Phillips wrote:
> It seems to me that everyone has an expectation that finalizers are
> attempted. And is my personal expectation. While Errors are not
> Exceptions they are being thrown via the Exception system and so it
> make sense to make a proper attempt at cleanup.

Errors are not recoverable - no cleanup is necessary.

> I will submit one piece of evidence toward this. OutOfMemoryError is
> valid to recover from and is only an error so that @nothrow and other
> restrictions do not apply to it, as it is always a potential problem.
> However not doing cleanup could prevent proper recover of OutOfMemory,
> and yes cleanup itself could fail, oh well.

OutOfMemory is deliberately made not recoverable, as I've almost never seen any application that can successfully recover from it. Making it non-recoverable also means that pure functions can allocate memory.


> Many times the Error comes from code which doesn't exist in release.
> This means it is safe to cleanup and do other operations, but you
> can't rely on it for program flow. This is where I like having the
> current state. It allows my environment to be returned to the original
> state (remove temporary files) without having to create an Error
> handling tree too.

If you're throwing recoverable exceptions in your debug code, make them derived from Exception, not Error.
_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals

March 14, 2012
> If you're throwing recoverable exceptions in your debug code, make them derived from Exception, not Error.

Contracts aren't supposed to throw Exceptions as you can't rely on
them for program flow.
_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals

March 15, 2012
On 15 March 2012 00:19, Brad Roberts <braddr@puremagic.com> wrote:
> Actually, the interaction of errors with @nothrow is a very specific part of the problem.  @nothrow allows the compiler to NOT setup the infrastructure to catch throwables at all.  This allows for some useful optimizations.  So, saying that Errors can be caught means that they have to be dis-allowed in @nothrow functions too.

That seems easily fixable to me.

Since nothrow is transitive, cases where an Error is thrown are always
known. In ThrowStatement:toIR() in s2ir.c, could check if it's a
nothrow function and call a separate
function, rather than _d_throwc, for an Error thrown inside a nothrow function.

This could do nothing more than set a flag 'thrown from
nothrow'/'unsafe' inside Error.
That leaves only the case of system exceptions on Windows.
Conservatively, they could also be set to 'unsafe'. Really if you're
going to catch one of those guys, you'd better catch them right next
to the event anyway.

The 'unsafe' flag may or may not affect stack unwinding (Maybe that
could even be a setting in the runtime).
But regardless, the catch handler would at least know if it could be
sure that stack unwinding had happened, or not.

Then, if we do this, it remains safe to catch an AssertError from a unit test.


Are there any other issues?
_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals

March 15, 2012
On Mar 14, 2012, at 4:42 PM, Walter Bright <walter@digitalmars.com> wrote:

> 
> 
> On 3/12/2012 7:07 PM, Sean Kelly wrote:
>> On Mar 12, 2012, at 5:35 PM, Walter Bright<walter@digitalmars.com>  wrote:
>> 
>>> 
>>> On 3/12/2012 2:39 PM, Sean Kelly wrote:
>>>> On Mar 12, 2012, at 2:30 PM, Walter Bright wrote:
>>>>> On 3/12/2012 12:34 PM, Sean Kelly wrote:
>>>>>> I'm on the fence about whether attempting cleanup when an Error is thrown is desired behavior.  If there is no cleanup, why allow Errors to be caught at all?  We may as well simply call abort() at the point they're thrown.
>>>>>> 
>>>>> So that an informative message can be printed, the backup engaged, attempt to shut down gracefully, log the failure details to a file, etc.
>>>> … none of which may work if scope(exit) calls weren't run when the stack was unwound, since acquired mutexes would still be locked, etc.  I'd feel a lot less safe with having effectively done a longjmp across code that normally assumes finalization than with whatever the cause of the assertion did in the first place.
>>>> 
>>> It's understood it may not work.
>> So what's the reason to not call finalizers?
>> 
> 
> The program is corrupted at that point. The less code one attempts to run, the better.

Is the program really corrupted though?  Errors are typically generated when a condition check fails, but typically before things go completely off the rails. I agree that errors typically shouldn't be recoverable because they generally indicate a problem in the program logic, but that doesn't mean the program is already in a bad state. I use C at my day job so my perspective may be a bit skewed, but when the program is corrupted there I don't get any indication of that until much later, at which point I agree that doing anything but abort with a message is a bad idea.

It seems there may be somewhat of a difference between D and SafeD here, because the latter should be immune to memory corruption (which is what I think of when you say the program is corrupted). So for SafeD I'd expect most errors to come from contract clauses and RangeErrors. Should D still make things worse by not attempting any cleanup?  I'll admit I'm torn.
_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals
March 15, 2012

Sent from my iPhone

On Mar 15, 2012, at 12:29 PM, Sean Kelly <sean@invisibleduck.org> wrote:

> It seems there may be somewhat of a difference between D and SafeD here, because the latter should be immune to memory corruption (which is what I think of when you say the program is corrupted). So for SafeD I'd expect most errors to come from contract clauses and RangeErrors. Should D still make things worse by not attempting any cleanup?  I'll admit I'm torn.

Is it legal to catch an error in SafeD? Based in the discussion in this thread, I think the answer should be "no". Given that, I don't think SafeD should go out of its way to make unsafe code safer.
_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals

March 15, 2012
Walter Bright, el 14 de marzo a las 16:42 me escribiste:
> On 3/12/2012 7:07 PM, Sean Kelly wrote:
> >On Mar 12, 2012, at 5:35 PM, Walter Bright<walter@digitalmars.com>  wrote:
> >
> >>
> >>On 3/12/2012 2:39 PM, Sean Kelly wrote:
> >>>On Mar 12, 2012, at 2:30 PM, Walter Bright wrote:
> >>>>On 3/12/2012 12:34 PM, Sean Kelly wrote:
> >>>>>I'm on the fence about whether attempting cleanup when an Error is thrown is desired behavior.  If there is no cleanup, why allow Errors to be caught at all?  We may as well simply call abort() at the point they're thrown.
> >>>>>
> >>>>So that an informative message can be printed, the backup engaged, attempt to shut down gracefully, log the failure details to a file, etc.
> >>>… none of which may work if scope(exit) calls weren't run when the stack was unwound, since acquired mutexes would still be locked, etc.  I'd feel a lot less safe with having effectively done a longjmp across code that normally assumes finalization than with whatever the cause of the assertion did in the first place.
> >>>
> >>It's understood it may not work.
> >So what's the reason to not call finalizers?
> 
> The program is corrupted at that point. The less code one attempts to run, the better.

Why? That's not always the case. And what could happen if you run cleanup code in a program that you say is completely invalid? So why would you care if the program gets more corrupted?

In the cases where the program is not completely in a corrupted state, running the finalizers make totally sense, in the case where a program is corrupted, it really doesn't matter, it's corrupted anyway. So why sacrificing a case where catching errors doing cleanup is useful for a case where it really doesn't matter?

This is specially bad if a memory allocation fail is an Error. It basically forces you to check every allocation for a failure and translate it yourself to some kind of Exception if you are being careful to write some code that can survive to a memory allocation failure.

Why on earth do you want to make life miserable to people that have some
valid use case for this, just to avoid corrupting a little more
a program that's already corrupted.

Also adding special cases is ALWAYS confusing and error prone. Please, please, please don't make errors a broken special case, unless you have a very strong reason.

-- 
Leandro Lucarella (AKA luca)                     http://llucax.com.ar/
----------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------
La esperanza es una amiga que nos presta la ilusión.
_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals
March 15, 2012

On 3/14/2012 4:52 PM, Jesse Phillips wrote:
>> If you're throwing recoverable exceptions in your debug code, make them
>> derived from Exception, not Error.
> Contracts aren't supposed to throw Exceptions as you can't rely on
> them for program flow.
>

Right. Contract failures must not be recoverable.
_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals

March 15, 2012
Walter Bright, el 14 de marzo a las 16:45 me escribiste:
> >I will submit one piece of evidence toward this. OutOfMemoryError is valid to recover from and is only an error so that @nothrow and other restrictions do not apply to it, as it is always a potential problem. However not doing cleanup could prevent proper recover of OutOfMemory, and yes cleanup itself could fail, oh well.
> 
> OutOfMemory is deliberately made not recoverable, as I've almost never seen any application that can successfully recover from it. Making it non-recoverable also means that pure functions can allocate memory.

Really? It seems that you never worked in a memory constrained system. There are applications that *really* need to take care about this.

Even you say *almost*, so I guess you actually acknowledge their
existence. If you go this route, please know that you'll make
D a language not suitable for this king of applications.

-- 
Leandro Lucarella (AKA luca)                     http://llucax.com.ar/
----------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------
Please could you stop the noise, I'm trying to get some rest
From all the unborn chicken voices in my head
What's that...? (I may be paranoid, but not an android)
_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals

March 15, 2012

On 3/15/2012 9:29 AM, Sean Kelly wrote:
> On Mar 14, 2012, at 4:42 PM, Walter Bright<walter@digitalmars.com>  wrote:
>
>>
>> On 3/12/2012 7:07 PM, Sean Kelly wrote:
>>> On Mar 12, 2012, at 5:35 PM, Walter Bright<walter@digitalmars.com>   wrote:
>>>
>>>> On 3/12/2012 2:39 PM, Sean Kelly wrote:
>>>>> On Mar 12, 2012, at 2:30 PM, Walter Bright wrote:
>>>>>> On 3/12/2012 12:34 PM, Sean Kelly wrote:
>>>>>>> I'm on the fence about whether attempting cleanup when an Error is thrown is desired behavior.  If there is no cleanup, why allow Errors to be caught at all?  We may as well simply call abort() at the point they're thrown.
>>>>>>>
>>>>>> So that an informative message can be printed, the backup engaged, attempt to shut down gracefully, log the failure details to a file, etc.
>>>>> … none of which may work if scope(exit) calls weren't run when the stack was unwound, since acquired mutexes would still be locked, etc.  I'd feel a lot less safe with having effectively done a longjmp across code that normally assumes finalization than with whatever the cause of the assertion did in the first place.
>>>>>
>>>> It's understood it may not work.
>>> So what's the reason to not call finalizers?
>>>
>> The program is corrupted at that point. The less code one attempts to run, the better.
> Is the program really corrupted though?

You cannot know that.

I really think that going down the path of thinking one can recover from programming bugs is the route to disaster. It goes against everything I know about how to make safe, reliable systems.

_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals