www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 8135] New: throwing Error runs finally handler

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8135

           Summary: throwing Error runs finally handler
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: dawg dawgfoto.de



cat > bug.d << CODE
extern(C) int printf(const char*, ...);

void foo()
{
    throw new Error("msg");
}

void main()
{
    try
        foo();
    finally
        printf("finally\n");
}
CODE

dmd -run bug

prints:
finally
object.Error: msg

expected:
object.Error: msg
----

The expected behavior was discussed in bug 7018 and on the mailing list.
Throwing Errors (http://forum.dlang.org/thread/1566418.J7qGkEti3s lyonel)

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 23 2012
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8135


Jonathan M Davis <jmdavisProg gmx.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |jmdavisProg gmx.com
         Resolution|                            |INVALID



PDT ---
This is not a bug. Per the lanugage, there is no guarantee that finally blocks,
scope statements, or destructors will be run when an Error is thrown, but
neither is there any guarantee that they _won't_ be. So, while relying on them
being executed when an Error is thrown is a bad idea, relying on them _not_
being executed when an Error is thrown is also a bad idea.

The current implementation _does_ always execute finally blocks, scope
statements, and destructors with Errors just like would occur with Exceptions,
and there is quite a lot of debate over whether the language should be changed
to reflect that. Walter is against it, but he's also one of the few who even
realized that the language didn't guarantee that they would be executed for
Errors. Other people who have been working on the exception handling in the
compiler and druntime _did_ think that it was guaranteed, and they wrote that
code with that in mind. In addition, I believe that the spec itself is actually
silent on the matter.

So, the short answer is that you should never rely on scope statements, finally
blocks, or destructors being run or not run when an Error is thrown.

A more thorough discussion of the issues is in this thread on dmd-internals:
http://forum.dlang.org/post/1566418.J7qGkEti3s lyonel

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 23 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8135




The current implementation _does_ always execute finally blocks, scope
statements, and destructors with Errors just like would occur with Exceptions
No they are not when you throw from a nothrow function. This is even worse when nothrow is inferred, because the actual behavior becomes instable.
So, the short answer is that you should never rely on scope statements, finally
blocks, or destructors being run or not run when an Error is thrown.
This is not an acceptable solution. The problem needs a clean decision and an according implementation or it will continue to create confusion. https://github.com/D-Programming-Language/druntime/pull/225#issuecomment-5857155 I'm wondering how the decision to use EH for fatal errors was made. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
May 23 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8135




PDT ---
Well, unstable behavior from an Error is pretty much a given if your program
doesn't die from it, unless it were treated completely like an Exception, in
which case you couldn't throw an Error (including OutOfMemoryError) from a
nothrow function, which would be unacceptable. Your program is pretty much
instantly in an unstable state as soon as an Error is thrown. It's just a
question of _how_ unstable, and the given implementation attempts far more
cleanup than is technically required according to Walter, which is a
double-edged sword, since that tends to make the code more stable when an Error
is thrown, but if your program is in a bad state thanks to whatever caused the
Error to be thrown, trying to do that cleanup could just make things worse.

Regardless, I completely agree that the situation needs to be clarified. We've
got the implementation going one way and Walter arguing another. And it would
certainly be better if it were guaranteed that finally and friends were never
executed when an Error is thrown than having them executed right now but
possibly not later when the implementation is tweaked. So, in principle, I
agree with the bug report, but as it stands, the current implementation is
within the required behavior.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 23 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8135


Alex Rønne Petersen <alex lycus.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |alex lycus.org



CEST ---
FWIW, I'm all for making Errors actually fatal and terminating the runtime
immediately, but then OutOfMemory*Error* HAS GOT TO GO. I use D as a systems
language, not as an applications language, and I *have* to be able to catch an
out of memory condition. I don't know why this was made an Error in the first
place, and in a systems language of all things. Yes, most developers may get it
wrong, but what about the few of us that *don't*?

Just my 2 cents/frustration as a developer writing a virtual machine in D...

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 23 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8135




PDT ---
Walter is of the firm belief that running out of memory is essentially
unrecoverable, so I don't see OutOfMemoryError ever being anything other than
an Error. If you really can't deal with that, you're probably going to have to
use something other than the GC for memory management (or wrap all GC
allocations in functions that can catch and deal with OutOfMemoryError
immediately after its thrown).

Even if the cleanup doesn't occur for Errors, it's quite possible to catch them
and handle them, and if you catch them very close to the throw point, you can
do so relatively safely. It's catching them far from the throw point that isn't
going to work.

http://d.puremagic.com/issues/show_bug.cgi?id=8137

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 23 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8135




CEST ---
From TDPL §9.4:

"If you catch a Throwable, you may only perform a number of simple operations;
most of the time, you probably want to print a message to the standard error or
a log file, attempt to save whatever you can save to a separate file, stiffen
that upper lip, and exit with as much dignity as possible."

This doesn't seem terribly encouraging... Essentially, I need to catch OOME and
continue full-blown program execution, which is very worrying.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 23 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8135




PDT ---
You should be able to do so under very limited circumstances, but it was
definitely a design decision of D that running out of memory would be
considered to be unrecoverable.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 23 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8135


Steven Schveighoffer <schveiguy yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |schveiguy yahoo.com



07:01:45 PDT ---

 FWIW, I'm all for making Errors actually fatal and terminating the runtime
 immediately, but then OutOfMemory*Error* HAS GOT TO GO.
Then you could mark almost nothing as nothrow. I think OutOfMemory should be an error. If you want to override the behavior because you have special circumstances, that should be possible (i.e. somehow prevent out of memory error from being thrown, but instead handle the situation in a different way). What about an enhancement of adding GC.mallocNoError and friends which instead return null when a memory block is not available instead of throwing? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
May 24 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8135


jens.k.mueller gmx.de changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jens.k.mueller gmx.de



I don't see why there should be no way to do some simple cleanup on an Error.
Testing in contracts is useful and does no harm. Maybe Walter can give a
concrete example where handling of Errors caused the program to be in a worse
state compared to exit right away given the programmer had a solid
understanding of what he was doing. Assuming I get an OutOfMemoryError having
chances sending last words is useful. I fail to see how this can make it worse.
It may be that he has seen to many misuses of handling errors. I would go with
a C++ attitude: "You can catch, scope guard, etc. any Throwable and even try to
recover from Exceptions. But Errors are not meant to be recovered from. You
have been warned."
TDPL also says that it's okay to do some cleanup.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 24 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8135




CEST ---


 FWIW, I'm all for making Errors actually fatal and terminating the runtime
 immediately, but then OutOfMemory*Error* HAS GOT TO GO.
Then you could mark almost nothing as nothrow.
True.
 
 I think OutOfMemory should be an error.  If you want to override the behavior
 because you have special circumstances, that should be possible (i.e. somehow
 prevent out of memory error from being thrown, but instead handle the situation
 in a different way).
 
 What about an enhancement of adding GC.mallocNoError and friends which instead
 return null when a memory block is not available instead of throwing?
That could work too. I really just want the GC to not assume that an allocation error is fatal. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
May 24 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8135




That could work too. I really just want the GC to not assume that an allocation
error is fatal.
You could simply override the behavior by providing your own 'extern(C) void onOutOfMemory()'. The linker will pick the one from druntime with the lowest precedence. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
May 24 2012
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=8135




CEST ---

That could work too. I really just want the GC to not assume that an allocation
error is fatal.
You could simply override the behavior by providing your own 'extern(C) void onOutOfMemory()'. The linker will pick the one from druntime with the lowest precedence.
I don't always want out of memory to be handled. In most cases, I do treat it as fatal, but in the few cases I don't, I just want to get a null value back from allocations in the core.memory module. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
May 24 2012