oscar-broman / exceptions

Exceptions for Pawn (SA-MP).
http://forum.sa-mp.com/showthread.php?t=425063
15 stars 0 forks source link

Catch runtime errors #4

Open oscar-broman opened 11 years ago

oscar-broman commented 11 years ago

crashdetect can report runtime errors to a public function - hook this function and use it to throw exceptions.

One of the problems with doing this is the outer public function will return 0 before OnRuntimeError, which makes it impossible to gracefully handle runtime errors in callbacks such as OnPlayerUpdate and OnPlayerCommandText.

Old code for this:

forward OnRuntimeError(code);
public OnRuntimeError(code) {
    if (s_UncaughtException) {
        return;
    }

    static const sc_messages[28][54] = {
        /* AMX_ERR_NONE      */ "None",
        /* AMX_ERR_EXIT      */ "Forced exit",
        /* AMX_ERR_ASSERT    */ "Assertion failed",
        /* AMX_ERR_STACKERR  */ "Stack/heap collision (insufficient stack size)",
        /* AMX_ERR_BOUNDS    */ "Array index out of bounds",
        /* AMX_ERR_MEMACCESS */ "Invalid memory access",
        /* AMX_ERR_INVINSTR  */ "Invalid instruction",
        /* AMX_ERR_STACKLOW  */ "Stack underflow",
        /* AMX_ERR_HEAPLOW   */ "Heap underflow",
        /* AMX_ERR_CALLBACK  */ "No (valid) native function callback",
        /* AMX_ERR_NATIVE    */ "Native function failed",
        /* AMX_ERR_DIVIDE    */ "Divide by zero",
        /* AMX_ERR_SLEEP     */ "sleep mode",
        /* 13 */                "reserved",
        /* 14 */                "reserved",
        /* 15 */                "reserved",
        /* AMX_ERR_MEMORY    */ "Out of memory",
        /* AMX_ERR_FORMAT    */ "Invalid/unsupported P-code file format",
        /* AMX_ERR_VERSION   */ "File is for a newer version of the AMX",
        /* AMX_ERR_NOTFOUND  */ "File or function is not found",
        /* AMX_ERR_INDEX     */ "Invalid index parameter (bad entry point)",
        /* AMX_ERR_DEBUG     */ "Debugger cannot run",
        /* AMX_ERR_INIT      */ "AMX not initialized (or doubly initialized)",
        /* AMX_ERR_USERDATA  */ "Unable to set user data field (table full)",
        /* AMX_ERR_INIT_JIT  */ "Cannot initialize the JIT",
        /* AMX_ERR_PARAMS    */ "Parameter error",
        /* AMX_ERR_DOMAIN    */ "Domain error, expression result does not fit in range",
        /* AMX_ERR_GENERAL   */ "General error (unknown or unspecific error)"
    };

    static msg[128];

    if (0 <= code < sizeof(sc_messages)) {
        format(msg, sizeof(msg), "runtime error %d: %s", code, sc_messages[code]);
    } else {
        format(msg, sizeof(msg), "runtime error %d", code);
    }

    if (funcidx(!"Exceptions_OnRuntimeError") != -1) {
        CallLocalFunction(!"Exceptions_OnRuntimeError", !"i", code);
    }

    ThrowError(msg);
}

#if defined _ALS_OnRuntimeError
    #undef OnRuntimeError
#else
    #define _ALS_OnRuntimeError
#endif

#define OnRuntimeError Exceptions_OnRuntimeError
oscar-broman commented 11 years ago

@Zeex do you think it would be possible to avoid when a runtime error happens?

For example: if you catch AMX_ERR_BOUNDS in OnPlayerCommandText, can you prevent SERVER: Unknown command?

Zeex commented 11 years ago

Should be possible now with this: https://github.com/Zeex/samp-plugin-crashdetect/commit/bbea212ce8c11e9b66d7c5b964040ec23c844adf

Now basically whatever you return in OnRuntimeError is returned to the server like if you return from the public itself. You can make a table of "default" return values for all SA-MP callbacks and return them in case of an error.

oscar-broman commented 11 years ago

Nice!