ID:101003
 
Not a bug
BYOND Version:474
Operating System:Windows XP Pro
Web Browser:Opera 9.80
Applies to:DM Language
Status: Not a bug

This is not a bug. It may be an incorrect use of syntax or a limitation in the software. For further discussion on the matter, please consult the BYOND forums.
Descriptive Problem Summary:

The ASSERT and CRASH procs stop the current procedure but the parent continues. This doesn't seem like reasonable behavior, especially because the same effect can be achieved with the return statement.

Numbered Steps to Reproduce Problem:

Code Snippet (if applicable) to Reproduce Problem:
proc/square_root(x)
if(x < 0)
CRASH("x must be positive.")
return sqrt(x)

mob/verb/Test()
var/a = square_root(-3)
world << a + 1


Expected Results:
runtime error: x must be positive.
proc name: square root (/proc/square_root)
usr: Forum_account (/mob)
src: null
call stack:
square root(-3)
Forum_account (/mob): Test()


Actual Results:
runtime error: x must be positive.
proc name: square root (/proc/square_root)
usr: Forum_account (/mob)
src: null
call stack:
square root(-3)
Forum_account (/mob): Test()

1

Note that the "1" is printed after the call to square_root, verifying that the parent proc/verb continues after a call crashes. The same thing (except for a slightly different error message) is seen if you use ASSERT(x >= 0) instead of CRASH.

Does the problem occur:
Every time? Or how often?
In other games?
In other user accounts?
On other computers?
It appears to happen every time.

When does the problem NOT occur?
When an actual error occurs, not one generated by ASSERT or CRASH.

Did the problem NOT occur in any earlier versions? If so, what was the last version that worked? (Visit http://www.byond.com/download/build to download old versions for testing.)
Not sure.

Workarounds:
proc/square_root(x)
if(x < 0)
. = new /mob()
CRASH("x must be positive.")
return sqrt(x)

mob/verb/Test()
var/a = square_root(-3)
world << a + 1


Because we know the parent proc is expecting a number we can return a mob with the hope that it uses this value in arithmetic and gets a "type mismatch" error that actually crashes the proc.
I don't think your information here is correct. You say when an actual error occurs the whole proc chain stops, but that isn't in fact true. Proc crashes have always stopped only the current proc but returned control to the parent. CRASH() and ASSERT() behave no differently than internal errors. All CRASH() does is call the internal crash handler that all procs use, but with a custom error message, and ASSERT() is just a #define macro in stddef.dm that calls CRASH().

I think this still belongs in the feature tracker where it was originally posted. The current behavior may not be what you want but it is not a bug.
Oh wow, errors don't stop execution of the parent proc. That's what I get for giving you the benefit of the doubt. Why on earth would you want the parent proc to continue with an invalid return value from the proc that crashed? Showing correctness of a program is difficult enough when you assume valid input, showing that code gracefully handles invalid input (because you lack the constructs to properly abort a routine) borders on impossible.
There's nothing wrong with the current behavior; it's just a different method of handling errors. In machine code the whole program will usually crash unless there's an exception handling system in place. Would crashing the entire proc chain be a better alternative? Maybe, but it couldn't be applied willy-nilly to the system because in existing games a runtime error may be only a minor inconvenience that doesn't take down the game, whereas crashing the whole proc chain could lead to a bad state that makes things unplayable. (Consider this happening in an event list, for instance. If the routine driving the event chain broke down, the game would cease to function, even if the error was something minor the author could easily fix the next day.)

I would not mind looking into a way to force a full proc chain shutdown for those programmers who would prefer that behavior. But I think overall a better option would be providing more robust, customizable error handling, a request that people have had for a long time now.
Would crashing the entire proc chain be a better alternative?

Being able to crash the entire call chain would absolutely be better. We don't have the ability to do that but there are times when it would be nice. Commands exist for exiting only the current proc.

Because the default behavior does not crash the entire call chain it would be difficult to implement exceptions and exception handling, but this would certainly be more ideal.

Even if the language was set up nicely to accommodate exceptions it would be a much more long-term goal. The change to ASSERT/CRASH seems like it could be implemented much sooner.
I think exception handling has come more into the realm of a medium-term goal, but I agree that providing an alternative crash method would be easier to implement for the short term. Of course the question then is how that should be specified, which would probably mean a world setting of some kind, so that can be hashed out on the feature thread.