View mode: basic / threaded / horizontal-split · Log in · Help
April 02, 2013
Re: DIP33: A standard exception hierarchy
On Tuesday, 2 April 2013 at 11:04:06 UTC, Dmitry Olshansky wrote:
> 02-Apr-2013 14:23, deadalnix пишет:
>> On Monday, 1 April 2013 at 22:46:49 UTC, Ali Çehreli wrote:
> [snip]
>> Not running cleanup code can transform a small issue in a big 
>> disaster
>> as running can make the problem worse.
>>
>> I don't think wiring in the language the fact that error don't 
>> run the
>> cleanup code is rather dangerous.
>>
>> If I had to propose something, it would be to handle error the 
>> same way
>> exception are handled, but propose a callback that is ran 
>> before the
>> error is throw, in order to allow for complete program stop 
>> based on
>> user logic.
>
> It's exactly what I have in mind as removing the exception 
> handling is something user can't recreate easily. On the other 
> hand "die on first signs of corruption" is as easy as a hook 
> that calls abort before unwind of Error.
>

It is possible to propose as a default a hook that fails 
everything and can be overriden.

> Time to petition Walter ;)
April 02, 2013
Re: DIP33: A standard exception hierarchy
On Monday, 1 April 2013 at 21:39:18 UTC, Dmitry Olshansky wrote:
> 01-Apr-2013 23:46, Lars T. Kyllingstad пишет:
>> On Monday, 1 April 2013 at 18:40:48 UTC, Dmitry Olshansky 
>> wrote:
>>> 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.
>
> Okay. I guess all of this goes to "Embedded D"/"D Lite" kind of 
> spec.
>
> Last thing - why separating ThreadException vs ProcessException 
> and should they have some base class? Just asking to see the 
> rationale behind it that is missing from DIP currently.

Well, I hadn't even considered that the same exception could be 
used for both.  I see the similarity between processes and 
threads, but I also think there is a difference in how/when/where 
you want to deal with errors related to them.  Say you have a 
function that starts a new process and then spawns a new thread 
to monitor it, and then the function fails for some reason.  This 
could be something you'd want to deal with on different levels, 
as a ProcessException could simply be that you got the wrong 
executable name, while a ThreadException would usually point to a 
much deeper issue.


>>> 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.

I have thought some more about it, and a basic serial comms error 
should probably be an IOException.  An error in a higher-level 
serial protocol, on the other hand, would be a NetworkException, 
and then the name doesn't suck so much.  CommException may still 
be better though, or maybe ProtocolException.

>>> 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?
>
> That's the trick - I hoped somebody will just say "aha!" and 
> add one :)
>
> The internal handle is hard to represent other then ... some 
> platform specific integer value. There goes generality... Other 
> then this there is a potential to stomp on feet of higher-level 
> abstraction on top of that handle.
>
> That last bit makes me reconsider the idea. While I see some 
> potential use for it I suspect it's too niche to fit in the 
> general hierarchy.
>
>> Bear in
>> mind that it should be general enough to cover all, or at 
>> least most,
>> kinds of I/O exceptions.
>
> Adding a Kind that states one of:
> out-of-data (read empty file)
> illegalOp (reading closed file, writing read-only file/socket)
> interrupted (operation was canceled by OS, connection forcibly 
> closed, disk ejected etc.)
> hardFault (OS reports hardware failure)

These are good suggestions, and seem general enough.

Lars
April 02, 2013
Re: DIP33: A standard exception hierarchy
On Monday, 1 April 2013 at 22:26:39 UTC, Jonathan M Davis wrote:
> On Monday, April 01, 2013 21:33:22 Lars T. Kyllingstad wrote:
>> 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.
>
> Except that they're extremely valuable when you need to catch 
> them. [...]
>
> try
> {
>  ...
> }
> catch(FileNotFoundException fnfe)
> {
>  //handling specific to missing files
> }
> catch(PermissionsDeniedException pde)
> {
>  //handling specific to lack of permissions
> }
> catch(FileExceptionfe
> {
>  //generic file handling error
> }
> catch(Exception e)
> {
>  //generic error handling
> }
>
> can be very valuable.

Well, personally, I don't think this is much better than a switch 
statement.

> In general, I'd strongly suggest having subclasses for
> the various "Kind"s in addition to the kind field. That way, 
> you have the
> specific exception types if you want to have separate catch 
> blocks for different
> error types, and you have the kind field if you just want to 
> catch the base
> exception.

Then you'd have two points of maintenance when you wish to add or 
remove an error category.

> If anything, exceptions are exactly the place where you want to 
> have derived
> classes with next to nothing in them, precisely because it's 
> the type that the
> catch mechanism uses to distinguish them.

catch is *one* mechanism, switch is another.  I propose to use 
catch for coarse-level handling (plus the cases where exceptions 
carry extra data), and switch for fine-level handling.

In my experience, most of the time, you don't even bother 
distinguishing between the finer categories.  If you can't open a 
file, well, that's that.  Tell the user why and ask them to try 
another file.  (I realise that this is highly arguable, of 
course.)

Lars
April 02, 2013
Re: DIP33: A standard exception hierarchy
On 2013-04-02 15:02, H. S. Teoh wrote:

> But what type will ex be, inside the catch block?

I was thinking the closest base type of the both exception types. It's 
basically what one would do if one would call a common function from 
multiple catch blocks.

-- 
/Jacob Carlborg
April 02, 2013
Re: DIP33: A standard exception hierarchy
On 2013-04-02 15:44, Steven Schveighoffer wrote:

> Yes, this could help.  But it's still not great.  One must still store a
> "type identifier" in the ex, or have to deal with casting to figure out
> what type ex is.

You would have the same problem if you used a common function for 
handling multiple exceptions.

> It also promotes creating a new type for every single catchable situation.
>
> Consider that we could create one exception type that contains an
> 'errno' member, and if we have the ability to run extra checks for
> catching you could do:
>
> catch(ErrnoException ex) if (ex.errno == EBADF || ex.errno == EBADPARAM)
> {
>     ...
> }

Is that so much better than:

catch (ErrnoException ex)
{
    if (ex.errno == EBADF || ex.errno == EBADPARAM)
    { /*handle exception */ }
    else
        throw ex;
}

> But if we must do it with types, we need:
>
> class ErrnoException(uint e) : Exception
> {
>     enum errno = e;
> }
>
> or worse, to make things easier to deal with we have:
>
> class ErrnoException : Exception
> {
>     int errno;
>     this(int errno) { this.errno = errno; }
> }
>
> class ErrnoExceptionT(uint e) : ErrnoException
> {
>     this() { super(e); }
> }
>
> which would be easier to deal with, but damn what a waste!  Either way,
> every time you catch another errno exception, we are talking about
> instantiating another type.

Does that matter? It still need to create a new instance for every 
exception thrown. Or are you planning on changing the "errno" field and 
rethrow the exception?

-- 
/Jacob Carlborg
April 02, 2013
Re: DIP33: A standard exception hierarchy
On 2013-04-02 17:56, Lars T. Kyllingstad wrote:

> In my experience, most of the time, you don't even bother distinguishing
> between the finer categories.  If you can't open a file, well, that's
> that.  Tell the user why and ask them to try another file.  (I realise
> that this is highly arguable, of course.)

I would say that there's a big difference if a file exist or if you 
don't have permission to access it. Think of the command line, you can 
easily misspell a filename, or forget to use "sudo".

-- 
/Jacob Carlborg
April 02, 2013
Re: DIP33: A standard exception hierarchy
On Tue, Apr 02, 2013 at 05:47:30PM +0200, Lars T. Kyllingstad wrote:
[...]
> I have thought some more about it, and a basic serial comms error
> should probably be an IOException.  An error in a higher-level serial
> protocol, on the other hand, would be a NetworkException, and then the
> name doesn't suck so much.  CommException may still be better though,
> or maybe ProtocolException.
[...]

ProtocolException sounds like a low-level TCP or IP exception. I think
NetworkException is still the best name, not overly specific, not overly
generic. CommException sounds a bit too vague to me.


T

-- 
What are you when you run out of Monet? Baroque.
April 02, 2013
Re: DIP33: A standard exception hierarchy
02-Apr-2013 20:39, H. S. Teoh пишет:
> On Tue, Apr 02, 2013 at 05:47:30PM +0200, Lars T. Kyllingstad wrote:
> [...]
>> I have thought some more about it, and a basic serial comms error
>> should probably be an IOException.  An error in a higher-level serial
>> protocol, on the other hand, would be a NetworkException, and then the
>> name doesn't suck so much.  CommException may still be better though,
>> or maybe ProtocolException.
> [...]
>
> ProtocolException sounds like a low-level TCP or IP exception. I think
> NetworkException is still the best name, not overly specific, not overly
> generic. CommException sounds a bit too vague to me.
>

Yeah, I've come to conclusion that NetworkException beats CommException 
in 90% of cases. The rest 10% can leave with Network being a sane name.


-- 
Dmitry Olshansky
April 02, 2013
Re: DIP33: A standard exception hierarchy
On 2013-04-02 11:59:39 +0000, Dmitry Olshansky <dmitry.olsh@gmail.com> said:

> 02-Apr-2013 15:35, Andrei Alexandrescu пишет:
>> On 4/2/13 7:24 AM, Dmitry Olshansky wrote:
>>> You might want to add Visitor pattern to Exceptions but it's darn messy
>>> to deal with and is an overkill most of the time.
>> 
>> Actually I think that's a good thing to do.
>> 
> 
> Why would be that? It doesn't solve the key problem of "try clause plus 
> a ton of semi-identical catches" used just to perform a mapping of X 
> handlers to Y subsets of errors. Plus visitor does the same dispatch 
> that is already addressed by exception handlers (or partly so).

What would be nice is some syntactic sugar for the following pattern:

	void handler(CommonExceptionType e)
	{
		// do something with exception
	}

	try { … }
	catch (FooException e) { handler(e); }
	catch (BarException e) { handler(e); }
	catch (BazException e) { handler(e); }

That could become:

	try { … }
	catch (CommonExceptionType e in FooException, BarException, BazException)
	{
		// do something with exception
	}

I've been secretly wishing for something like this, and not just in D.

-- 
Michel Fortin
michel.fortin@michelf.ca
http://michelf.ca/
April 02, 2013
Re: DIP33: A standard exception hierarchy
On Tue, Apr 02, 2013 at 09:43:20AM -0400, Andrei Alexandrescu wrote:
> On 4/2/13 7:59 AM, Dmitry Olshansky wrote:
> >02-Apr-2013 15:35, Andrei Alexandrescu пишет:
> >>On 4/2/13 7:24 AM, Dmitry Olshansky wrote:
> >>>You might want to add Visitor pattern to Exceptions but it's darn
> >>>messy to deal with and is an overkill most of the time.
> >>
> >>Actually I think that's a good thing to do.
> >>
> >
> >Why would be that? It doesn't solve the key problem of "try clause
> >plus a ton of semi-identical catches" used just to perform a mapping
> >of X handlers to Y subsets of errors. Plus visitor does the same
> >dispatch that is already addressed by exception handlers (or partly
> >so).
> 
> Visitor allows centralized and flexible handling of exceptions.
> 
> >If somebody comes up with a reasonable Visitor pattern for Exceptions
> >that is flexible and fast then sure let's see it. I just doubt it'll
> >help anything on its own in any case.
> 
> Well I think exceptions + factory + visitor is quite the connection.
[...]

Hmm. So one could have something like this, perhaps?

	void main() {
		try {
			dotDotDotMagic();
		} catch(Exception e) {
			e.handle(ExceptionHandler());
		}
	}
	class ExceptionHandler {
		void handle(IOException e) { ... }
		void handle(ParseException e) { ... }
		...
	}

Of course, this would be the lowered version of some nice syntactic
sugar that the compiler would translate into.

But I'm not sure how this offers an advantage over the current state of
things, though. How would you handle the case where some exception types
aren't handled by ExceptionHandler? How would you handle accepting
multiple exception types by the same handler code? How would you map
something like this to nicer syntax that isn't worse than the current
way of just manually defining a common function (or overloaded
functions) that handles the exception?

Or perhaps I didn't quite understand how you intend to implement the
visitor pattern in exceptions.


T

-- 
Knowledge is that area of ignorance that we arrange and classify. -- Ambrose Bierce
2 3 4 5 6 7 8 9 10
Top | Discussion index | About this forum | D home