Jump to page: 1 213  
Page
Thread overview
Exception/Error division in D
May 24, 2012
Denis Shelomovskij
May 24, 2012
Sean Kelly
May 24, 2012
Gor Gyolchanyan
May 24, 2012
Sean Kelly
May 25, 2012
Jacob Carlborg
May 29, 2012
Sean Kelly
May 30, 2012
deadalnix
May 30, 2012
deadalnix
May 30, 2012
Dmitry Olshansky
May 30, 2012
deadalnix
May 30, 2012
deadalnix
May 30, 2012
Jonathan M Davis
May 30, 2012
Don Clugston
May 30, 2012
Jonathan M Davis
May 30, 2012
Jacob Carlborg
May 30, 2012
Dmitry Olshansky
May 30, 2012
Jonathan M Davis
May 31, 2012
Jacob Carlborg
May 31, 2012
Jonathan M Davis
May 31, 2012
Jacob Carlborg
May 30, 2012
deadalnix
May 30, 2012
Sean Kelly
May 30, 2012
Don Clugston
May 30, 2012
Jonathan M Davis
May 31, 2012
Regan Heath
May 30, 2012
deadalnix
May 30, 2012
Jonathan M Davis
May 31, 2012
Kapps
May 31, 2012
Kapps
May 31, 2012
Sean Kelly
May 31, 2012
Walter Bright
May 31, 2012
deadalnix
Jun 01, 2012
Jouko Koski
May 31, 2012
deadalnix
May 31, 2012
Artur Skawina
May 31, 2012
deadalnix
May 30, 2012
deadalnix
May 30, 2012
Sean Kelly
May 30, 2012
Jens Mueller
May 30, 2012
Jens Mueller
May 30, 2012
Dmitry Olshansky
May 31, 2012
Walter Bright
May 31, 2012
deadalnix
runtime hook for Crash on Error
May 31, 2012
Dmitry Olshansky
May 31, 2012
David Nadlinger
May 31, 2012
Dmitry Olshansky
Jun 01, 2012
Walter Bright
Jun 01, 2012
Jens Mueller
Jun 01, 2012
Walter Bright
Jun 01, 2012
deadalnix
Jun 01, 2012
Dmitry Olshansky
Jun 01, 2012
Walter Bright
Jun 01, 2012
deadalnix
Jun 01, 2012
Jonathan M Davis
Jun 01, 2012
Dmitry Olshansky
Jun 01, 2012
Dmitry Olshansky
Jun 01, 2012
Walter Bright
Jun 01, 2012
Walter Bright
Jun 01, 2012
Dmitry Olshansky
Jun 04, 2012
Don Clugston
Jun 05, 2012
Don Clugston
Jun 05, 2012
Jonathan M Davis
Jun 05, 2012
Don Clugston
Jun 05, 2012
Dmitry Olshansky
Jun 05, 2012
Jonathan M Davis
Jun 06, 2012
Don Clugston
Jun 05, 2012
Sean Kelly
Jun 06, 2012
deadalnix
Jun 06, 2012
Sean Kelly
Jun 06, 2012
Dmitry Olshansky
Jun 06, 2012
deadalnix
Jun 05, 2012
deadalnix
Jun 01, 2012
Walter Bright
Jun 01, 2012
Artur Skawina
Jun 06, 2012
Jonathan M Davis
Jun 06, 2012
Jonathan M Davis
Jun 06, 2012
Jonathan M Davis
Jun 06, 2012
Jonathan M Davis
Jun 07, 2012
Timon Gehr
Jun 06, 2012
Timon Gehr
Jun 06, 2012
Timon Gehr
Jun 06, 2012
deadalnix
Jun 01, 2012
Walter Bright
Jun 01, 2012
Simen Kjaeraas
Jun 02, 2012
Walter Bright
Jun 02, 2012
Denis Shelomovskij
Jun 01, 2012
Jacob Carlborg
Jun 01, 2012
Walter Bright
May 31, 2012
Walter Bright
May 31, 2012
deadalnix
Jun 01, 2012
Walter Bright
Jun 01, 2012
deadalnix
Jun 01, 2012
Walter Bright
Jun 04, 2012
deadalnix
Jun 04, 2012
Don Clugston
May 31, 2012
Walter Bright
May 31, 2012
Jens Mueller
May 31, 2012
Walter Bright
May 31, 2012
Jens Mueller
Jun 01, 2012
Walter Bright
Jun 01, 2012
Jens Mueller
Jun 01, 2012
Walter Bright
Jun 01, 2012
deadalnix
Jun 01, 2012
Tobias Pankrath
Jun 01, 2012
Andrej Mitrovic
Jun 01, 2012
deadalnix
May 31, 2012
Sean Kelly
Jun 01, 2012
deadalnix
May 24, 2012
Let's talk about an abstract situation without caring about breaking existing code, current docs, implementation etc.

Definitions:
* an Exception is something that tigers scope guards and executes catch/finally blocks if thrown;
* an Error is something that doesn't do it.

As a result _we can't do any clean-up if an Error is thrown_ because scope guards and catch/finally blocks aren't executed and the program is in invalid state because of this. Of course it's theoretically possible to code without scope guards and catch/finally blocks but isn't applicably for a real project. E.g. in some editor if and Error is thrown there is no ability to save opened documents.


Main Question: What do you think can be an Error?

Can "Integer Divide by Zero" be an Error? Definitely, not.

Can "Access Violation" be an Error? No, because it's very common to access a field/virtual member function of a null object.

Can "Out of memory" be an Error? No, because e.g. if I read a user file that require me to create a large array (> 100 MiB, e.g.) I don't want to crash, but just tell, that "Dear user, the file can't be opened because it requires..."


So what am I think can be an Error? IMHO, nothing. Because throwing everything can indicate that program in very good/terribly bad state and compiler doesn't know anything about that. And because fatal error is fatal the program should just try to print error and close instead of throwing something.


Let's now return to the real D world. Current implementation treats Errors as Exceptions for now. Documentation keeps silence. All listed "can't be an error" cases are Errors (and it's terrible).

So why do we has Exception/Error division in D? Because of nothrow. Personally I don't need nothrow for that high cost of making D unusable for me. Lets realize and solve Exception/Error problem and solve nothrow in the second place.


Related links:
http://forum.dlang.org/thread/1566418.J7qGkEti3s@lyonel
http://d.puremagic.com/issues/show_bug.cgi?id=8135
http://d.puremagic.com/issues/show_bug.cgi?id=8136
http://d.puremagic.com/issues/show_bug.cgi?id=8137


P.S.
By the way, the only problem I see in current implementation is a luck of "Object finalized" assertion ("True disposable objects (add "Finalized!" assertion)" NG thread that didn't interest anybody).

-- 
Денис В. Шеломовский
Denis V. Shelomovskij
May 24, 2012
On May 24, 2012, at 3:27 AM, Denis Shelomovskij wrote:

> Let's talk about an abstract situation without caring about breaking existing code, current docs, implementation etc.
> 
> Definitions:
> * an Exception is something that tigers scope guards and executes catch/finally blocks if thrown;
> * an Error is something that doesn't do it.
> 
> As a result _we can't do any clean-up if an Error is thrown_ because scope guards and catch/finally blocks aren't executed and the program is in invalid state because of this. Of course it's theoretically possible to code without scope guards and catch/finally blocks but isn't applicably for a real project. E.g. in some editor if and Error is thrown there is no ability to save opened documents.
> 
> 
> Main Question: What do you think can be an Error?
> 
> Can "Integer Divide by Zero" be an Error? Definitely, not.
> 
> Can "Access Violation" be an Error? No, because it's very common to access a field/virtual member function of a null object.
> 
> Can "Out of memory" be an Error? No, because e.g. if I read a user file that require me to create a large array (> 100 MiB, e.g.) I don't want to crash, but just tell, that "Dear user, the file can't be opened because it requires..."
> 
> 
> So what am I think can be an Error? IMHO, nothing. Because throwing everything can indicate that program in very good/terribly bad state and compiler doesn't know anything about that. And because fatal error is fatal the program should just try to print error and close instead of throwing something.

I agree.  However, the benefit to having Error is so that nothrow can exist.  If every exception were considered recoverable then we'd have to throw out nothrow as well, since basically anything can generate an access violation, for example.  Or we could weaken nothrow so that it didn't even allow memory allocations, which would render it largely useless.  For what it's worth, the D runtime does do clean-up for both Errors and Exceptions today.  The only difference is codgen for scope statements and such inside nothrow functions--instead of being rewritten as try/finally the on-exit code is just inserted at the proper scope exit points.


> Let's now return to the real D world. Current implementation treats Errors as Exceptions for now. Documentation keeps silence. All listed "can't be an error" cases are Errors (and it's terrible).
> 
> So why do we has Exception/Error division in D? Because of nothrow. Personally I don't need nothrow for that high cost of making D unusable for me. Lets realize and solve Exception/Error problem and solve nothrow in the second place.

Seems you already know this.  Oops.  I'm inclined to agree, personally.  nothrow is less useful in D than in C++ because it's safe to throw from dtors in D (problems related to throwing from a finalizer during a GC collection aside--that's more an exception safety issue for the GC than anything else).
May 24, 2012
I'd say, removing nothrow and Error from D would be a good idea. Everybody throws Exception from anywhere. What would be the practical reason not to do that (besides potentially breaking code)?

On Thu, May 24, 2012 at 9:51 PM, Sean Kelly <sean@invisibleduck.org> wrote:

> On May 24, 2012, at 3:27 AM, Denis Shelomovskij wrote:
>
> > Let's talk about an abstract situation without caring about breaking
> existing code, current docs, implementation etc.
> >
> > Definitions:
> > * an Exception is something that tigers scope guards and executes
> catch/finally blocks if thrown;
> > * an Error is something that doesn't do it.
> >
> > As a result _we can't do any clean-up if an Error is thrown_ because
> scope guards and catch/finally blocks aren't executed and the program is in invalid state because of this. Of course it's theoretically possible to code without scope guards and catch/finally blocks but isn't applicably for a real project. E.g. in some editor if and Error is thrown there is no ability to save opened documents.
> >
> >
> > Main Question: What do you think can be an Error?
> >
> > Can "Integer Divide by Zero" be an Error? Definitely, not.
> >
> > Can "Access Violation" be an Error? No, because it's very common to
> access a field/virtual member function of a null object.
> >
> > Can "Out of memory" be an Error? No, because e.g. if I read a user file
> that require me to create a large array (> 100 MiB, e.g.) I don't want to crash, but just tell, that "Dear user, the file can't be opened because it requires..."
> >
> >
> > So what am I think can be an Error? IMHO, nothing. Because throwing
> everything can indicate that program in very good/terribly bad state and compiler doesn't know anything about that. And because fatal error is fatal the program should just try to print error and close instead of throwing something.
>
> I agree.  However, the benefit to having Error is so that nothrow can exist.  If every exception were considered recoverable then we'd have to throw out nothrow as well, since basically anything can generate an access violation, for example.  Or we could weaken nothrow so that it didn't even allow memory allocations, which would render it largely useless.  For what it's worth, the D runtime does do clean-up for both Errors and Exceptions today.  The only difference is codgen for scope statements and such inside nothrow functions--instead of being rewritten as try/finally the on-exit code is just inserted at the proper scope exit points.
>
>
> > Let's now return to the real D world. Current implementation treats
> Errors as Exceptions for now. Documentation keeps silence. All listed "can't be an error" cases are Errors (and it's terrible).
> >
> > So why do we has Exception/Error division in D? Because of nothrow.
> Personally I don't need nothrow for that high cost of making D unusable for me. Lets realize and solve Exception/Error problem and solve nothrow in the second place.
>
> Seems you already know this.  Oops.  I'm inclined to agree, personally.
>  nothrow is less useful in D than in C++ because it's safe to throw from
> dtors in D (problems related to throwing from a finalizer during a GC
> collection aside--that's more an exception safety issue for the GC than
> anything else).




-- 
Bye,
Gor Gyolchanyan.


May 24, 2012
On Thu, 24 May 2012 06:27:12 -0400, Denis Shelomovskij <verylonglogin.reg@gmail.com> wrote:

> Let's talk about an abstract situation without caring about breaking existing code, current docs, implementation etc.
>
> Definitions:
> * an Exception is something that tigers scope guards and executes catch/finally blocks if thrown;
> * an Error is something that doesn't do it.

I'll give you a different definition:

* an Exception is something that can be handled far away from the context of the error, because the system can safely unwind the stack.
* an Error must be handled at the point the error occurred, or the program state is by definition invalid.

>
> As a result _we can't do any clean-up if an Error is thrown_ because scope guards and catch/finally blocks aren't executed and the program is in invalid state because of this. Of course it's theoretically possible to code without scope guards and catch/finally blocks but isn't applicably for a real project. E.g. in some editor if and Error is thrown there is no ability to save opened documents.
>
>
> Main Question: What do you think can be an Error?
>
> Can "Integer Divide by Zero" be an Error? Definitely, not.

I agree with you there.  However, the problem isn't nearly as bad as you say.  The runtime doesn't actually deal with SIGFPE on Unix based systems, and most places where an "Error" is thrown, it's within asserts, which are compiled out in release code.

If you get one of these, you can handle the signal.  I think on Windows it's handled for you, but there should be a way to intercept this and do recovery.

> Can "Access Violation" be an Error? No, because it's very common to access a field/virtual member function of a null object.

I'd argue this is unrecoverable.  Access Violation results from corruption, and the damage has already been done.  Even a null pointer access can be the cause of previous corruption.  There is no "recovery" from memory corruption.  There is no way to plan for it.

Now, if you want to handle it specifically for your program, that should be doable, at your own risk.  But there's no way throwing an Exception is a valid result.

> Can "Out of memory" be an Error? No, because e.g. if I read a user file that require me to create a large array (> 100 MiB, e.g.) I don't want to crash, but just tell, that "Dear user, the file can't be opened because it requires..."

Right, out of memory is only an error if your program's invariant depends on the memory allocation.  You can plan for the above easily enough, but not realistically for all tasks and all library code that require allocation.

For example, let's say you are restructuring a hash table, and you reallocate some nodes.  You have half transferred over the old structure to the new structure, and you run out of memory.  How to recover from this?

In summary, I think we can adjust Windows divide by zero errors to allow you to handle them manually, the Posix version is fine (no Error is generated), access violations are unequivocally Errors, and out of memory should be fixable by making allocation routines that do not throw (just return null).

An interesting idea would be to allow a global "handler" for all errors.  So if you throw an Exception, it unwinds the stack like normal.  If you throw an Error, it checks a handler to see if you want to handle that error (via registering a function/delegate), and if not handled throws Error without properly unwinding the stack.

-Steve
May 24, 2012
On May 24, 2012, at 11:39 AM, Steven Schveighoffer wrote:

> On Thu, 24 May 2012 06:27:12 -0400, Denis Shelomovskij <verylonglogin.reg@gmail.com> wrote:
> 
>> Let's talk about an abstract situation without caring about breaking existing code, current docs, implementation etc.
>> 
>> Definitions:
>> * an Exception is something that tigers scope guards and executes catch/finally blocks if thrown;
>> * an Error is something that doesn't do it.
> 
> I'll give you a different definition:
> 
> * an Exception is something that can be handled far away from the context of the error, because the system can safely unwind the stack.
> * an Error must be handled at the point the error occurred, or the program state is by definition invalid.

This is a good point.  OutOfMemory conditions aside, the only time I'd want to recover from an Error condition was at the point the event occurred, not somewhere up the stack.


>> Can "Access Violation" be an Error? No, because it's very common to access a field/virtual member function of a null object.
> 
> I'd argue this is unrecoverable.  Access Violation results from corruption, and the damage has already been done.  Even a null pointer access can be the cause of previous corruption.  There is no "recovery" from memory corruption.  There is no way to plan for it.
> 
> Now, if you want to handle it specifically for your program, that should be doable, at your own risk.  But there's no way throwing an Exception is a valid result.

Right.  Recovery is potentially valid at the point of failure, not somewhere up the stack.


>> Can "Out of memory" be an Error? No, because e.g. if I read a user file that require me to create a large array (> 100 MiB, e.g.) I don't want to crash, but just tell, that "Dear user, the file can't be opened because it requires..."
> 
> Right, out of memory is only an error if your program's invariant depends on the memory allocation.  You can plan for the above easily enough, but not realistically for all tasks and all library code that require allocation.
> 
> For example, let's say you are restructuring a hash table, and you reallocate some nodes.  You have half transferred over the old structure to the new structure, and you run out of memory.  How to recover from this?

I think it's fair to expect code that allocates be exception-safe in the face of allocation errors.  I know I'm always very careful with containers so that an allocation failure doesn't result in corruption, for example.


> In summary, I think we can adjust Windows divide by zero errors to allow you to handle them manually, the Posix version is fine (no Error is generated), access violations are unequivocally Errors, and out of memory should be fixable by making allocation routines that do not throw (just return null).

It would be kind of cool if there were some sort of unified way to handle system-generated errors, though I don't know that this is practical.  signals sort of work on Windows, but I'm pretty sure the contextual sigaction stuff does not.


> An interesting idea would be to allow a global "handler" for all errors.  So if you throw an Exception, it unwinds the stack like normal.  If you throw an Error, it checks a handler to see if you want to handle that error (via registering a function/delegate), and if not handled throws Error without properly unwinding the stack.

^^ this
May 24, 2012
On Thu, 24 May 2012 15:33:07 -0400, Sean Kelly <sean@invisibleduck.org> wrote:

> On May 24, 2012, at 11:39 AM, Steven Schveighoffer wrote:
>

>>> Can "Out of memory" be an Error? No, because e.g. if I read a user file that require me to create a large array (> 100 MiB, e.g.) I don't want to crash, but just tell, that "Dear user, the file can't be opened because it requires..."
>>
>> Right, out of memory is only an error if your program's invariant depends on the memory allocation.  You can plan for the above easily enough, but not realistically for all tasks and all library code that require allocation.
>>
>> For example, let's say you are restructuring a hash table, and you reallocate some nodes.  You have half transferred over the old structure to the new structure, and you run out of memory.  How to recover from this?
>
> I think it's fair to expect code that allocates be exception-safe in the face of allocation errors.  I know I'm always very careful with containers so that an allocation failure doesn't result in corruption, for example.

I don't think it's fair to expect *all* code to be able to safely recover from an out of memory exception.  I pretty much *never* write code that worries about out of memory errors.  One cannot always expect an operation involving hundreds of allocations to be atomic.

That being said, we should provide a mechanism so you can handle it, as it's reliably detectable and very recoverable in many situations.

-Steve
May 25, 2012
On 2012-05-24 21:33, Sean Kelly wrote:

> This is a good point.  OutOfMemory conditions aside, the only time I'd want to recover from an Error condition was at the point the event occurred, not somewhere up the stack.

You never feel you want to catch at the top level, print a sensible error message and then exit the application? Instead of the application just disappearing for user.

If the application can't print the error message it just fails in the same way as if you had not catch the error.

-- 
/Jacob Carlborg
May 29, 2012
On May 24, 2012, at 11:50 PM, Jacob Carlborg wrote:

> On 2012-05-24 21:33, Sean Kelly wrote:
> 
>> This is a good point.  OutOfMemory conditions aside, the only time I'd want to recover from an Error condition was at the point the event occurred, not somewhere up the stack.
> 
> You never feel you want to catch at the top level, print a sensible error message and then exit the application? Instead of the application just disappearing for user.

Well sure, but I wouldn't consider this recovery.
May 30, 2012
Le 24/05/2012 12:27, Denis Shelomovskij a écrit :
> Let's talk about an abstract situation without caring about breaking
> existing code, current docs, implementation etc.
>
> Definitions:
> * an Exception is something that tigers scope guards and executes
> catch/finally blocks if thrown;
> * an Error is something that doesn't do it.
>
> As a result _we can't do any clean-up if an Error is thrown_ because
> scope guards and catch/finally blocks aren't executed and the program is
> in invalid state because of this. Of course it's theoretically possible
> to code without scope guards and catch/finally blocks but isn't
> applicably for a real project. E.g. in some editor if and Error is
> thrown there is no ability to save opened documents.
>
>
> Main Question: What do you think can be an Error?
>
> Can "Integer Divide by Zero" be an Error? Definitely, not.
>
> Can "Access Violation" be an Error? No, because it's very common to
> access a field/virtual member function of a null object.
>
> Can "Out of memory" be an Error? No, because e.g. if I read a user file
> that require me to create a large array (> 100 MiB, e.g.) I don't want
> to crash, but just tell, that "Dear user, the file can't be opened
> because it requires..."
>
>
> So what am I think can be an Error? IMHO, nothing. Because throwing
> everything can indicate that program in very good/terribly bad state and
> compiler doesn't know anything about that. And because fatal error is
> fatal the program should just try to print error and close instead of
> throwing something.
>
>
> Let's now return to the real D world. Current implementation treats
> Errors as Exceptions for now. Documentation keeps silence. All listed
> "can't be an error" cases are Errors (and it's terrible).
>
> So why do we has Exception/Error division in D? Because of nothrow.
> Personally I don't need nothrow for that high cost of making D unusable
> for me. Lets realize and solve Exception/Error problem and solve nothrow
> in the second place.
>
>
> Related links:
> http://forum.dlang.org/thread/1566418.J7qGkEti3s@lyonel
> http://d.puremagic.com/issues/show_bug.cgi?id=8135
> http://d.puremagic.com/issues/show_bug.cgi?id=8136
> http://d.puremagic.com/issues/show_bug.cgi?id=8137
>
>
> P.S.
> By the way, the only problem I see in current implementation is a luck
> of "Object finalized" assertion ("True disposable objects (add
> "Finalized!" assertion)" NG thread that didn't interest anybody).
>

The fact that error don't trigger scope and everything is nonsensial.

Today, we know how to implement exception with NO RUNTIME COST when exception isn't thrown. No reason not to do it, except executable size. As this is a specific constraint, we may want to enable it by a compiler switch, but not by default.

I see Error as problem that can occur anywhere in any piece of code.

I think D have some flaw in Exception management. See Segfault vs NullPointerException discussions in that very forum. Segfault may be OK for some application, but not for a server app that need to be robust.

Error exists because of nothrow. As some exceptions can be thrown ANYWHERE, we need a way to separate what is expected to fail, and that have to be handled to be nothrow, and what can go wrong anywhere (basically, when druntime cannot do its job for some reasons).
May 30, 2012
Le 24/05/2012 20:39, Steven Schveighoffer a écrit :
> I'd argue this is unrecoverable. Access Violation results from
> corruption, and the damage has already been done. Even a null pointer
> access can be the cause of previous corruption. There is no "recovery"
> from memory corruption. There is no way to plan for it.
>
> Now, if you want to handle it specifically for your program, that should
> be doable, at your own risk. But there's no way throwing an Exception is
> a valid result.
>

https://github.com/D-Programming-Language/druntime/pull/187

I think this is a mandatory patch due to nullable types by default. Arguably, nullable by default is the problem.
« First   ‹ Prev
1 2 3 4 5 6 7 8 9 10 11