March 03, 2012
On Saturday, 3 March 2012 at 22:24:59 UTC, Walter Bright wrote:
> On 3/3/2012 12:29 PM, Sandeep Datta wrote:
>> I would recommend doing what Microsoft does in this case, use SEH (Structured exception handling) on windows i.e. use OS facilities to trap and convert hardware exceptions into software exceptions.
>
> D for Windows already does that.
>
> It's been there for 10 years, and turns out to be a solution looking for a problem.

Getting a stack trace without having to start a debugger is kinda nice.
March 04, 2012
> It's been there for 10 years, and turns out to be a solution looking for a problem.

I beg to differ, the ability to catch and respond to such asynchronous exceptions is vital to the stable operation of long running software.

It is not hard to see how this can be useful in programs which depend on plugins to extend functionality (e.g. IIS, Visual Studio, OS with drivers as plugins etc). A misbehaving plugin has the potential to bring down the whole house if hardware exceptions cannot be safely handled within the host application. Thus the inability of handling such exceptions undermines D's ability to support dynamically loaded modules of any kind and greatly impairs modularity.

Also note hardware exceptions are not limited to segfaults there are other exceptions like division by zero, invalid operation, floating point exceptions (overflow, underflow) etc.

Plus by using this approach (SEH) you can eliminate the software null checks and avoid taking a hit on performance.

So in conclusion I think it will be worth our while to supply something like a NullReferenceException (and maybe NullPointerException for raw pointers) which will provide more context than a simple segfault (and that too without a core dump). Additional information may include things like a stacktrace (like Vladimir said in another post) with line numbers, file/module names etc. Please take a look at C#'s exception hierarchy for some inspiration (not that you need any but it's nice to have some consistency across languages too). I am just a beginner in D but I hope D has something like exception chaining in C# using  which we can chain exceptions as we go to capture the chain of events which led to failure.
March 04, 2012
On Sunday, 4 March 2012 at 02:53:54 UTC, Sandeep Datta wrote:
> Thus the inability of handling such exceptions undermines D's ability to support dynamically loaded modules of any kind and greatly impairs modularity.

You can catch it in D (on Windows):

import std.stdio;
void main() {
	int* a;
	try {
		*a = 0;
	} catch(Throwable t) {
		writefln("I caught it! %s", t.msg);
	}
}

dmd test9
test9
I caught it! Access Violation

March 04, 2012
> You can catch it in D (on Windows):

This is great. All we have to do now is provide a more specific exception (say NullReferenceException) so that the programmer has the ability to provide a specific exception handler for NullReferenceException etc.

I gave it a try on Linux but unfortunately it leads to a segfault (DMD 2.056, x86-64).
March 04, 2012
On Sunday, 4 March 2012 at 03:15:19 UTC, Sandeep Datta wrote:
> All we have to do now is provide a more specific exception (say NullReferenceException) so that the programmer has the ability to provide a specific exception handler for NullReferenceException etc.

Looks like it is pretty easy to do. Check out

dmd2/src/druntime/src/rt/deh.d

The Access Violation error is thrown on about
line 635. There's a big switch that handles a bunch
of errors.

> I gave it a try on Linux but unfortunately it leads to a segfault

Yeah, Linux does it as a signal which someone has
tried to turn into an exception before, which kinda
works but is easy to break. (I don't remember
exactly why it didn't work right, but there
were problems.)
March 04, 2012
On 3/3/2012 6:53 PM, Sandeep Datta wrote:
>> It's been there for 10 years, and turns out to be a solution looking for a
>> problem.
>
> I beg to differ, the ability to catch and respond to such asynchronous
> exceptions is vital to the stable operation of long running software.
>
> It is not hard to see how this can be useful in programs which depend on plugins
> to extend functionality (e.g. IIS, Visual Studio, OS with drivers as plugins
> etc). A misbehaving plugin has the potential to bring down the whole house if
> hardware exceptions cannot be safely handled within the host application. Thus
> the inability of handling such exceptions undermines D's ability to support
> dynamically loaded modules of any kind and greatly impairs modularity.
>
> Also note hardware exceptions are not limited to segfaults there are other
> exceptions like division by zero, invalid operation, floating point exceptions
> (overflow, underflow) etc.
>
> Plus by using this approach (SEH) you can eliminate the software null checks and
> avoid taking a hit on performance.
>
> So in conclusion I think it will be worth our while to supply something like a
> NullReferenceException (and maybe NullPointerException for raw pointers) which
> will provide more context than a simple segfault (and that too without a core
> dump). Additional information may include things like a stacktrace (like
> Vladimir said in another post) with line numbers, file/module names etc. Please
> take a look at C#'s exception hierarchy for some inspiration (not that you need
> any but it's nice to have some consistency across languages too). I am just a
> beginner in D but I hope D has something like exception chaining in C# using
> which we can chain exceptions as we go to capture the chain of events which led
> to failure.

As I said, it already does that (on Windows). There is an access violation exception. Try it on windows, you'll see it.

1. SEH isn't portable. There's no way to make it work under non-Windows systems.

2. Converting SEH to D exceptions is not necessary to make a stack trace dump work.

3. Intercepting and recovering from seg faults, div by 0, etc., all sounds great on paper. In practice, it is almost always wrong. The only exception (!) to the rule is when sandboxing a plugin (as you suggested). Making such a sandbox work is highly system specific, and doesn't always fit into the D exception model (in fact, it never does outside of Windows).


March 04, 2012
On Sun, Mar 04, 2012 at 04:29:27AM +0100, Adam D. Ruppe wrote:
> On Sunday, 4 March 2012 at 03:15:19 UTC, Sandeep Datta wrote:
> >All we have to do now is provide a more specific exception (say NullReferenceException) so that the programmer has the ability to provide a specific exception handler for NullReferenceException etc.
> 
> Looks like it is pretty easy to do. Check out
> 
> dmd2/src/druntime/src/rt/deh.d
> 
> The Access Violation error is thrown on about
> line 635. There's a big switch that handles a bunch
> of errors.
> 
> >I gave it a try on Linux but unfortunately it leads to a segfault
> 
> Yeah, Linux does it as a signal which someone has tried to turn into an exception before, which kinda works but is easy to break. (I don't remember exactly why it didn't work right, but there were problems.)

Yeah, according to the Posix specs, trying to continue execution after catching SIGSEGV or SIGILL is ... to say the least, extremely dangerous. Basically you'll have to unwind the stack and run the rest of the program inside signal handler context, which means certain operations (like calling signal unsafe syscalls) are not guaranteed to do what you'd expect.

Of course, there are ways around it, but it does depend on the specific way Linux implements signal handling, which is not guaranteed to not change across Linux versions (because it's not part of the Posix spec). So it would be very fragile, and prone to nasty bugs.


T

-- 
This is a tpyo.
March 04, 2012
On Sat, Mar 03, 2012 at 07:34:50PM -0800, Walter Bright wrote: [...]
> 3. Intercepting and recovering from seg faults, div by 0, etc., all sounds great on paper. In practice, it is almost always wrong. The only exception (!) to the rule is when sandboxing a plugin (as you suggested). Making such a sandbox work is highly system specific, and doesn't always fit into the D exception model (in fact, it never does outside of Windows).
[...]

I wonder if there's some merit to a std.sandbox module in Phobos...

In Linux (any Posix), for example, it could run the sandbox code inside a fork()ed process, and watch for termination by signal, for example. Data could be returned via a pipe, or maybe a shared memory segment of some sort.

Don't know how this would work on Windows, but presumably there are clean ways of doing it that doesn't endanger the health of the process creating the sandbox.


T

-- 
Freedom of speech: the whole world has no right *not* to hear my spouting off!
March 04, 2012
On 3/3/2012 8:20 PM, H. S. Teoh wrote:
> Don't know how this would work on Windows, but presumably there are
> clean ways of doing it that doesn't endanger the health of the process
> creating the sandbox.

If you're dealing with plugins from an unknown source, it's a good design to separate plugins and such as entirely separate processes. Then, when one goes down, it cannot bring down anyone else, since there is no shared address space.

They can communicate with the OS-supplied interprocess communications API.
March 04, 2012
On Sun, 04 Mar 2012 03:53:53 +0100, Sandeep Datta <datta.sandeep@gmail.com> wrote:

>> It's been there for 10 years, and turns out to be a solution looking for a problem.
>
> I beg to differ, the ability to catch and respond to such asynchronous exceptions is vital to the stable operation of long running software.
>
> It is not hard to see how this can be useful in programs which depend on plugins to extend functionality (e.g. IIS, Visual Studio, OS with drivers as plugins etc). A misbehaving plugin has the potential to bring down the whole house if hardware exceptions cannot be safely handled within the host application. Thus the inability of handling such exceptions undermines D's ability to support dynamically loaded modules of any kind and greatly impairs modularity.
>
A misbehaving plugin could easily corrupt your process. Destroying data
is always much worse than crashing. The only sensible reaction to an async
exception is dumping/tracing. If you want stable plugins you'll have to run
them in another process.