View mode: basic / threaded / horizontal-split · Log in · Help
April 01, 2013
Re: DIP33: A standard exception hierarchy
01-Apr-2013 15:08, Lars T. Kyllingstad пишет:
> It's time to clean up this mess.
>
> http://wiki.dlang.org/DIP33

Overall neat.

1. Where to define this hierarchy.
Captain the obvious says std.exception, but can we fit all of them there?

2. ProcessException is IMHO a system exception. Plus some RTOses systems 
may not have processes in the usaul POSIX sense. It needs some thought.

3. I assume that NetworkingException should rather be NetworkException. 
Not only that but I truly hope it deals with network-only events (like 
resolver errors, host unreachable etc.) not with normal I/O Exceptions 
happening on sockets. It could get tricky to separate the two on some OSes.

4. A quiz as an extension of 3 - where a e.g. serial port exceptions 
would fit in this hierarchy? Including Parity errors, data overrun etc.
Let's think a bit ahead and pick names wisely.
Maybe turn NetworkException --> Comm(unication)Exception, I dunno.

5. Continuing the above - a failed call (in-system) of a general purpose 
IPC library would be a ... SystemException? A network exception? Should 
it matter to the user?

6. I like ParseException. Wondering if could be generalized a bit - in a 
sense it's a "bad format"/"malformed" exception. For instance corrupt DB 
file reporting ParseException (= bad format) is rather wacky.

7. DocParseExcpetion ---> TextParseException there is a notion of a 
binary "document" (e.g. BSON databases like Mongo DB).

8. For IOExcpetion we might consider adding an indication on which file 
handle the problem happened and/or if it's closed/invalid/"mostly fine" 
that.

That's it so far. We'll see if there is more ;)
-- 
Dmitry Olshansky
April 01, 2013
Re: DIP33: A standard exception hierarchy
On Monday, 1 April 2013 at 12:12:56 UTC, Lars T. Kyllingstad 
wrote:
>
> I think OutOfMemory should not be restricted by nothrow, and I 
> propose to solve it as described above.

More precisely:  In principle, I think OutOfMemory *should* be 
restricted by nothrow, but it would break too much code, and be 
far too annoying, to be feasible. :)

Lars
April 01, 2013
Re: DIP33: A standard exception hierarchy
On Monday, 1 April 2013 at 14:58:42 UTC, Jacob Carlborg wrote:
> On 2013-04-01 13:08, Lars T. Kyllingstad wrote:
>> It's time to clean up this mess.
>>
>> http://wiki.dlang.org/DIP33
>
> In general I think it looks good. I also think it's really 
> needed.
>
> Don't IOException and ProcessException need a "kind" field as 
> well?

Maybe.  The ones that have such fields will probably need more 
Kind enum members too.  What's in the DIP are simply the ones 
that I could think of when I wrote it.

Lars
April 01, 2013
Re: DIP33: A standard exception hierarchy
On Monday, 1 April 2013 at 17:28:11 UTC, H. S. Teoh wrote:
> On Mon, Apr 01, 2013 at 01:08:15PM +0200, Lars T. Kyllingstad 
> wrote:
>> It's time to clean up this mess.
>> 
>> http://wiki.dlang.org/DIP33
>
> I'd prefer "NetworkException" instead of "NetworkingException" 
> (long
> name with no added advantage).

Agreed.  I have changed it now.


> About the use of enums in FilesystemException, 
> NetworkingException,
> etc.: I understand the rationale for them, but this also makes 
> them
> closed for extension. Is there anything fundamentally wrong with
> creating subclasses of these exceptions instead of attempting 
> to cover
> *all* possible problems in a single enum?

Phobos/druntime devs will have the opportunity to add enum fields 
to cover every error category in those libraries, and the users 
themselves can still extend the classes the "normal" way.  As you 
may have noticed, the first member of each enum is "unknown", 
which is meant for errors that do not fall into any of the other 
categories.  (There may be a better name for this, like "other", 
and maybe there should be a separate enum member called 
"userDefined"?)

My problem with subclasses is that they are a rather heavyweight 
addition to an API.  If they bring no substance (such as extra 
data), I think they are best avoided.


> I like the use of chaining to attach errno or windows system 
> errors to
> exceptions. This solves the problem of errno's not being easily 
> mapped
> to one of the standard exception classes. It's sort of the 
> reverse of
> what chaining was intended for (another exception being thrown 
> while the
> first one was in transit), but I haven't actually seen any real 
> use case
> for the latter, so we might as well use it for the purpose here.
>
> The only thing is, this makes library code a bit trickier to 
> write.
> Maybe Phobos needs to provide some kind of standard (though
> system-specific) way of mapping errno, windows error codes, 
> etc., into
> one of the standard exception types, so that this mapping won't 
> have to
> be duplicated all over the place. Obviously it can't be 
> completely
> automatic, since some errno's may map to different exceptions 
> depending
> on context, but *some* amount of mapping would be highly 
> desirable to
> avoid code duplication.

This is a good idea.


> Another nice thing to have (not sure how practical it will be) 
> is to add
> more information to the exceptions under Exception. To truly 
> free us
> from the tendency to just invent GetoptException, XMLException,
> RegexException, etc., we need to consider that sometimes you 
> *do* want
> to know where the exception came from. For example, you could 
> be calling
> std.getopt from some generic initialization code that does 
> other stuff
> too, both of which may throw a ConversionException, say. 
> Sometimes you
> need to distinguish between them (display a command-line syntax 
> help in
> one case, just display an error in the other case, depending on 
> where
> the exception came from). One solution is to add a locus field 
> to
> Exception:
>
> 	class Exception : Error {
> 		...
> 		/// Where this exception came from
> 		/// E.g., "std.getopt", "std.xml",
> 		/// "my.program.init.complexconv", etc..
> 		string locus;
> 	}
>
> This way the catching code doesn't have to downcast, guess, or 
> do some
> ugly non-portable hacking to figure out what to do.
>
> This field should probably be automatically filled by 
> Exception's ctor,
> so that it doesn't require additional burden on the programmer.
>
> I'm not 100% sure the module name should be used in this field, 
> but the
> idea is that it should contain some way of identifying the 
> origin of the
> exception that can be programmatically identified.

My first though was: "Isn't this what the stack trace is for?", 
but then again, that's rather bothersome to parse 
programmatically.  I'm not completely sold on the idea of tagging 
exceptions with their modules of origin, but I don't have any 
good alternatives, either.

Lars
April 01, 2013
Re: DIP33: A standard exception hierarchy
01-Apr-2013 20:00, John Colvin пишет:
> On Monday, 1 April 2013 at 12:12:56 UTC, Lars T. Kyllingstad wrote:
>
>> But if all cleanup code is bypassed, what is the point in using the
>> exception mechanism in the first place?  Why not just abort() and be
>> done with it?
>>
>> I can think of two reasons for throwing an Error rather than aborting
>> directly:
>> 1. You want a kind of "graceful" shutdown, in which destructors *are*
>> called and make their best attempt at cleaning things up.
>> 2. You want to catch it at some point, and perform some manual cleanup.
>>
>> But if (1) does not happen, can you even hope to do something useful
>> with (2)?  Your program is in the worst possible state it can be!
>
> I'm no expert on these things, but:
>
> Any chance of being in an invalid state - > undefined behaviour
>
> Undefined behaviour - > your destructors/cleanup routine could in theory
> do anything.
>

While a solid point I'd argue the opposite is more applicable.
The proponents of "Undefined bahaviour" is "anything can happen" let's 
just die fail flat on 2 counts:

1. Label all "bad things" s as undefined where it's more often 
system-defined or implementation defined. Out of memory is another one. 
Processor dependent behavior is another one (e.g. shift beyond word 
wideness).

2. Second that "anything can happen" thus "let's not try destructors and 
cleanup" just call abort.  In fact if you escalate the point of 
"anything" there is no guarantee that abort call will ...e-hm... 
actually call the process termination routine (or that C run-time is 
intact).

> Therefore, you're better off not trying to cleanup if program state
> could be invalid.

Data is corrupted no matter if you just fail to write it in a consistent 
state (sudden assertion in some 3-rd party library) or corrupt 
accidentally by bad write (during cleanup on corrupted RAM).

Therefore you should always try to orderly cleanup but do not rely on it 
to actually work at all circumstances (thus backups, commits/save 
points, watchdogs and whatnot).


-- 
Dmitry Olshansky
April 01, 2013
Re: DIP33: A standard exception hierarchy
On Monday, 1 April 2013 at 18:40:48 UTC, Dmitry Olshansky wrote:
> 01-Apr-2013 15:08, Lars T. Kyllingstad пишет:
>> It's time to clean up this mess.
>>
>> http://wiki.dlang.org/DIP33
>
> Overall neat.
>
> 1. Where to define this hierarchy.
> Captain the obvious says std.exception, but can we fit all of 
> them there?

Some of them have to be in core.exception.  Personally, I think 
the rest of the base hierarchy should be in std.exception.  In 
fact, I think the "standard hierarchy" should be defined as 
"what's in core.exception and std.exception".

If we identify cases where modules absolutely *must* extend these 
classes for extremely specific purposes, this can be done within 
the module.

> 2. ProcessException is IMHO a system exception. Plus some 
> RTOses systems may not have processes in the usaul POSIX sense. 
> It needs some thought.

Well, I *don't* think ProcessException is a SystemException. :)  
And if druntime/Phobos is to be used on OSes that don't have 
processes, there are other adaptations that have to be made that 
are probably more fundamental.


> 3. I assume that NetworkingException should rather be 
> NetworkException. Not only that but I truly hope it deals with 
> network-only events (like resolver errors, host unreachable 
> etc.) not with normal I/O Exceptions happening on sockets. It 
> could get tricky to separate the two on some OSes.

I have changed the name.  I have the same view of the 
NetworkException/IOException separation as you.

> 4. A quiz as an extension of 3 - where a e.g. serial port 
> exceptions would fit in this hierarchy? Including Parity 
> errors, data overrun etc.
> Let's think a bit ahead and pick names wisely.
> Maybe turn NetworkException --> Comm(unication)Exception, I 
> dunno.

Good question, I dunno either. :)  I agree we should think about 
it.


> 5. Continuing the above - a failed call (in-system) of a 
> general purpose IPC library would be a ... SystemException? A 
> network exception? Should it matter to the user?

Note that I am only saying that the standard exceptions should 
cover *most* error categories.  100% is not feasible, and we 
shouldn't even try.  This may be one of the exceptions (haha) to 
the rule.

> 6. I like ParseException. Wondering if could be generalized a 
> bit - in a sense it's a "bad format"/"malformed" exception. For 
> instance corrupt DB file reporting ParseException (= bad 
> format) is rather wacky.

I agree, and welcome all suggestions for better names.


> 7. DocParseExcpetion ---> TextParseException there is a notion 
> of a binary "document" (e.g. BSON databases like Mongo DB).

Agreed.


> 8. For IOExcpetion we might consider adding an indication on 
> which file handle the problem happened and/or if it's 
> closed/invalid/"mostly fine" that.

Which form do you suggest that such an indicator should take? 
Bear in mind that it should be general enough to cover all, or at 
least most, kinds of I/O exceptions.

Lars
April 01, 2013
Re: DIP33: A standard exception hierarchy
On Monday, 1 April 2013 at 17:42:07 UTC, Jesse Phillips wrote:
> On Monday, 1 April 2013 at 11:08:16 UTC, Lars T. Kyllingstad 
> wrote:
>> It's time to clean up this mess.
>>
>> http://wiki.dlang.org/DIP33
>
> I like the idea, I think some specifics may need worked out 
> (already being discussed)
>
> You're likely purposely avoiding this. But when the subject of 
> a "Exception Hierarchy" comes up thoughts of having specific 
> modules to house the exceptions come up. I don't think this is 
> the primary concern, but my position is to keep the exceptions 
> in their std implementation/use.

You're right, I was purposely avoiding it in the DIP. :) But I 
have given the matter some thought; see my answer to Dmitry.

Lars
April 01, 2013
Re: DIP33: A standard exception hierarchy
On 2013-04-01 21:22, Lars T. Kyllingstad wrote:

> Maybe.  The ones that have such fields will probably need more Kind enum
> members too.  What's in the DIP are simply the ones that I could think
> of when I wrote it.

I was think of what you wrote in the text: "failure to start a process, 
failure to wait for a process".

-- 
/Jacob Carlborg
April 01, 2013
Re: DIP33: A standard exception hierarchy
On Monday, April 01, 2013 21:17:27 Lars T. Kyllingstad wrote:
> On Monday, 1 April 2013 at 12:12:56 UTC, Lars T. Kyllingstad
> 
> wrote:
> > I think OutOfMemory should not be restricted by nothrow, and I
> > propose to solve it as described above.
> 
> More precisely: In principle, I think OutOfMemory *should* be
> restricted by nothrow, but it would break too much code, and be
> far too annoying, to be feasible. :)

There's really no point in making it so that OutOfMemory prevents nothrow, as 
it's pretty much assumed by the runtime that OutOfMemory means that you're 
toast (hence why it's not an Exception). If anything making it prevent nothrow 
would be a disaster, rendering nothrow nigh on unusable in many situations 
where it should work just fine. The whole point of nothrow is to indicate that 
no Exceptions can be thrown (and therefore anything that's required by 
exceptions doesn't have to be done). Errors don't fall in that category at 
all, especially in light of the fact that there's no guarantee that any clean-
up will be done when a non-Exception is thrown.

- Jonathan M Davis
April 01, 2013
Re: DIP33: A standard exception hierarchy
On Monday, April 01, 2013 13:23:49 monarch_dodra wrote:
> On Monday, 1 April 2013 at 11:08:16 UTC, Lars T. Kyllingstad
> 
> wrote:
> > It's time to clean up this mess.
> > 
> > http://wiki.dlang.org/DIP33
> 
> A quick comment about your "Error" section. You say:
> 
> "In general, Errors should not be caught, primarily because they
> indicate that the program logic is compromised, and that the
> program may therefore be in an invalid state from which there is
> no recovery".
> 
> It is actually much worst than that: errors bypass the entire
> exception handling mechanism, blasting through code that would
> handle destructors, and even flying through functions that are
> nothrow. They don't just indicate a "potential" invalid state,
> they actually *put* the program in an invalid state, from which
> there is no recovery.
> 
> That is the main mechanical difference between an "error" and an
> "exception", it is not just a philosophical "logic vs runtime".
> 
> --------
> 
> Under this situation, I'm wondering how the "OutOfMemory" is
> dealt with (you don't explain).

It's not an Exception, so no clean-up is guaranteed. _Any_ Throwable which is 
not an Exception risks no clean-up being done. Error really has nothing to do 
with it beyond the fact that it's not an Exception.

Now, the reality of the matter is that the current implementation _does_ 
generally do clean-up when non-Exceptions are thrown (the major exception 
being code dealing with nothrow functions IIRC), but according to Walter, 
there's no guarantee that that's the case (and I'm not sure that he's 
particularly happy that any clean-up happens at all for non-Exceptions like it 
does right now).

- Jonathan M Davis
1 2 3 4 5 6
Top | Discussion index | About this forum | D home