Split runtime abort/asserts and app abort/assert. Always log and abort normally from native code. Display a dialog and exit silently when aborting/asserting from wasm code or bindings bound checks
This commit is contained in:
		
							parent
							
								
									82e4d0e08b
								
							
						
					
					
						commit
						dbc0c0e124
					
				|  | @ -135,8 +135,8 @@ def bindgen(apiName, spec, **kwargs): | |||
|                     s += retTypeCName + '* __retPtr = (' + retTypeCName + '*)((char*)_mem + *(i32*)&_sp[0]);\n' | ||||
| 
 | ||||
|                     s += '\t{\n' | ||||
|                     s += '\t\tOC_ASSERT(((char*)__retPtr >= (char*)_mem) && (((char*)__retPtr - (char*)_mem) < m3_GetMemorySize(runtime)), "return pointer is out of bounds");\n' | ||||
|                     s += '\t\tOC_ASSERT((char*)__retPtr + sizeof(' + retTypeCName + ') <= ((char*)_mem + m3_GetMemorySize(runtime)), "return pointer is out of bounds");\n' | ||||
|                     s += '\t\tOC_ASSERT_DIALOG(((char*)__retPtr >= (char*)_mem) && (((char*)__retPtr - (char*)_mem) < m3_GetMemorySize(runtime)), "return pointer is out of bounds");\n' | ||||
|                     s += '\t\tOC_ASSERT_DIALOG((char*)__retPtr + sizeof(' + retTypeCName + ') <= ((char*)_mem + m3_GetMemorySize(runtime)), "return pointer is out of bounds");\n' | ||||
|                     s += '\t}\n' | ||||
| 
 | ||||
|             for argIndex, arg in enumerate(decl['args']): | ||||
|  | @ -178,8 +178,8 @@ def bindgen(apiName, spec, **kwargs): | |||
|                         printError("binding '" + name + "' missing pointer length decoration for param '" + argName + "'") | ||||
|                     else: | ||||
|                         s += '\t{\n' | ||||
|                         s += '\t\tOC_ASSERT(((char*)'+ argName + ' >= (char*)_mem) && (((char*)'+ argName +' - (char*)_mem) < m3_GetMemorySize(runtime)), "parameter \''+argName+'\' is out of bounds");\n' | ||||
|                         s += '\t\tOC_ASSERT((char*)' + argName + ' + ' | ||||
|                         s += '\t\tOC_ASSERT_DIALOG(((char*)'+ argName + ' >= (char*)_mem) && (((char*)'+ argName +' - (char*)_mem) < m3_GetMemorySize(runtime)), "parameter \''+argName+'\' is out of bounds");\n' | ||||
|                         s += '\t\tOC_ASSERT_DIALOG((char*)' + argName + ' + ' | ||||
| 
 | ||||
|                         proc = argLen.get('proc') | ||||
|                         if proc != None: | ||||
|  |  | |||
|  | @ -7,7 +7,8 @@ | |||
| **************************************************************************/ | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| #include "app/app.h" | ||||
| #include "util/memory.h" | ||||
| #include "util/strings.h" | ||||
| #include "platform_debug.c" | ||||
| //----------------------------------------------------------------
 | ||||
| // Logging
 | ||||
|  | @ -102,14 +103,7 @@ _Noreturn void oc_abort_ext(const char* file, const char* function, int line, co | |||
|                                 note.ptr); | ||||
| 
 | ||||
|     oc_log_error(msg.ptr); | ||||
| 
 | ||||
|     oc_str8_list options = { 0 }; | ||||
|     oc_str8_list_push(scratch.arena, &options, OC_STR8("OK")); | ||||
| 
 | ||||
|     oc_alert_popup(OC_STR8("Fatal Error"), msg, options); | ||||
| 
 | ||||
|     //TODO: could terminate more gracefully?
 | ||||
|     exit(-1); | ||||
|     abort(); | ||||
| } | ||||
| 
 | ||||
| _Noreturn void oc_assert_fail(const char* file, const char* function, int line, const char* src, const char* fmt, ...) | ||||
|  | @ -130,12 +124,5 @@ _Noreturn void oc_assert_fail(const char* file, const char* function, int line, | |||
|                                 oc_str8_ip(note)); | ||||
| 
 | ||||
|     oc_log_error(msg.ptr); | ||||
| 
 | ||||
|     oc_str8_list options = { 0 }; | ||||
|     oc_str8_list_push(scratch.arena, &options, OC_STR8("OK")); | ||||
| 
 | ||||
|     oc_alert_popup(OC_STR8("Assertion Failed"), msg, options); | ||||
| 
 | ||||
|     //TODO: could terminate more gracefully?
 | ||||
|     exit(-1); | ||||
|     abort(); | ||||
| } | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| *  See LICENSE.txt for licensing information | ||||
| * | ||||
| **************************************************************************/ | ||||
| #include <stdarg.h> | ||||
| #include "platform_debug.h" | ||||
| 
 | ||||
| typedef struct oc_log_config | ||||
|  |  | |||
							
								
								
									
										118
									
								
								src/runtime.c
								
								
								
								
							
							
						
						
									
										118
									
								
								src/runtime.c
								
								
								
								
							|  | @ -95,20 +95,6 @@ u64 orca_check_cstring(IM3Runtime runtime, const char* ptr) | |||
|     return (len + 1); //include null-terminator
 | ||||
| } | ||||
| 
 | ||||
| void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const char* function, int line, const char* msg) | ||||
| { | ||||
|     M3ErrorInfo errInfo = { 0 }; | ||||
|     m3_GetErrorInfo(runtime, &errInfo); | ||||
|     if(errInfo.message && res == errInfo.result) | ||||
|     { | ||||
|         oc_abort_ext(file, function, line, "%s: %s (%s)", msg, res, errInfo.message); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         oc_abort_ext(file, function, line, "%s: %s", msg, res); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void oc_bridge_window_set_title(oc_wasm_str8 title) | ||||
| { | ||||
|     oc_str8 nativeTitle = oc_wasm_str8_to_native(title); | ||||
|  | @ -133,6 +119,80 @@ void oc_bridge_clipboard_set_string(oc_wasm_str8 value) | |||
|     oc_runtime_clipboard_set_string(&__orcaApp.clipboard, value); | ||||
| } | ||||
| 
 | ||||
| void oc_assert_fail_dialog(const char* file, | ||||
|                            const char* function, | ||||
|                            int line, | ||||
|                            const char* test, | ||||
|                            const char* fmt, | ||||
|                            ...) | ||||
| { | ||||
|     oc_arena_scope scratch = oc_scratch_begin(); | ||||
| 
 | ||||
|     va_list ap; | ||||
|     va_start(ap, fmt); | ||||
|     oc_str8 note = oc_str8_pushfv(scratch.arena, fmt, ap); | ||||
|     va_end(ap); | ||||
| 
 | ||||
|     oc_str8 msg = oc_str8_pushf(scratch.arena, | ||||
|                                 "Assertion failed in function %s() in file \"%s\", line %i:\n%s\nNote: %.*s\n", | ||||
|                                 function, | ||||
|                                 file, | ||||
|                                 line, | ||||
|                                 test, | ||||
|                                 oc_str8_ip(note)); | ||||
| 
 | ||||
|     oc_log_error(msg.ptr); | ||||
| 
 | ||||
|     oc_str8_list options = { 0 }; | ||||
|     oc_str8_list_push(scratch.arena, &options, OC_STR8("OK")); | ||||
| 
 | ||||
|     oc_alert_popup(OC_STR8("Assertion Failed"), msg, options); | ||||
|     exit(-1); | ||||
| 
 | ||||
|     oc_scratch_end(scratch); | ||||
| } | ||||
| 
 | ||||
| void oc_abort_ext_dialog(const char* file, const char* function, int line, const char* fmt, ...) | ||||
| { | ||||
|     oc_arena_scope scratch = oc_scratch_begin(); | ||||
| 
 | ||||
|     va_list ap; | ||||
|     va_start(ap, fmt); | ||||
|     oc_str8 note = oc_str8_pushfv(scratch.arena, fmt, ap); | ||||
|     va_end(ap); | ||||
| 
 | ||||
|     oc_str8 msg = oc_str8_pushf(scratch.arena, | ||||
|                                 "Fatal error in function %s() in file \"%s\", line %i:\n%.*s\n", | ||||
|                                 function, | ||||
|                                 file, | ||||
|                                 line, | ||||
|                                 oc_str8_ip(note)); | ||||
| 
 | ||||
|     oc_log_error(msg.ptr); | ||||
| 
 | ||||
|     oc_str8_list options = { 0 }; | ||||
|     oc_str8_list_push(scratch.arena, &options, OC_STR8("OK")); | ||||
| 
 | ||||
|     oc_alert_popup(OC_STR8("Fatal Error"), msg, options); | ||||
|     exit(-1); | ||||
| 
 | ||||
|     oc_scratch_end(scratch); | ||||
| } | ||||
| 
 | ||||
| void oc_wasm3_trap(IM3Runtime runtime, M3Result res, const char* file, const char* function, int line, const char* msg) | ||||
| { | ||||
|     M3ErrorInfo errInfo = { 0 }; | ||||
|     m3_GetErrorInfo(runtime, &errInfo); | ||||
|     if(errInfo.message && res == errInfo.result) | ||||
|     { | ||||
|         oc_abort_ext_dialog(file, function, line, "%s: %s (%s)", msg, res, errInfo.message); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         oc_abort_ext_dialog(file, function, line, "%s: %s", msg, res); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void oc_bridge_log(oc_log_level level, | ||||
|                    int functionLen, | ||||
|                    char* function, | ||||
|  | @ -441,13 +501,13 @@ i32 orca_runloop(void* user) | |||
|     M3Result res = m3_ParseModule(app->env.m3Env, &app->env.m3Module, (u8*)app->env.wasmBytecode.ptr, app->env.wasmBytecode.len); | ||||
|     if(res) | ||||
|     { | ||||
|         ORCA_WASM3_ABORT(app->env.m3Runtime, res, "The application couldn't parse its web assembly module"); | ||||
|         OC_WASM3_TRAP(app->env.m3Runtime, res, "The application couldn't parse its web assembly module"); | ||||
|     } | ||||
| 
 | ||||
|     res = m3_LoadModule(app->env.m3Runtime, app->env.m3Module); | ||||
|     if(res) | ||||
|     { | ||||
|         ORCA_WASM3_ABORT(app->env.m3Runtime, res, "The application couldn't load its web assembly module into the runtime"); | ||||
|         OC_WASM3_TRAP(app->env.m3Runtime, res, "The application couldn't load its web assembly module into the runtime"); | ||||
|     } | ||||
|     m3_SetModuleName(app->env.m3Module, bundleNameCString); | ||||
| 
 | ||||
|  | @ -472,7 +532,7 @@ i32 orca_runloop(void* user) | |||
|     res = m3_CompileModule(app->env.m3Module); | ||||
|     if(res) | ||||
|     { | ||||
|         ORCA_WASM3_ABORT(app->env.m3Runtime, res, "The application couldn't compile its web assembly module"); | ||||
|         OC_WASM3_TRAP(app->env.m3Runtime, res, "The application couldn't compile its web assembly module"); | ||||
|     } | ||||
| 
 | ||||
|     //NOTE: Find and type check event handlers.
 | ||||
|  | @ -558,7 +618,7 @@ i32 orca_runloop(void* user) | |||
|         M3Result res = m3_Call(exports[OC_EXPORT_ON_INIT], 0, 0); | ||||
|         if(res) | ||||
|         { | ||||
|             ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); | ||||
|             OC_WASM3_TRAP(app->env.m3Runtime, res, "Runtime error"); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -571,7 +631,7 @@ i32 orca_runloop(void* user) | |||
|         M3Result res = m3_Call(exports[OC_EXPORT_FRAME_RESIZE], 2, args); | ||||
|         if(res) | ||||
|         { | ||||
|             ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); | ||||
|             OC_WASM3_TRAP(app->env.m3Runtime, res, "Runtime error"); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -616,7 +676,7 @@ i32 orca_runloop(void* user) | |||
|                     M3Result res = m3_Call(exports[OC_EXPORT_RAW_EVENT], 1, args); | ||||
|                     if(res) | ||||
|                     { | ||||
|                         ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); | ||||
|                         OC_WASM3_TRAP(app->env.m3Runtime, res, "Runtime error"); | ||||
|                     } | ||||
| #else | ||||
|                     oc_log_error("oc_on_raw_event() is not supported on big endian platforms"); | ||||
|  | @ -647,7 +707,7 @@ i32 orca_runloop(void* user) | |||
|                         M3Result res = m3_Call(exports[OC_EXPORT_FRAME_RESIZE], 2, args); | ||||
|                         if(res) | ||||
|                         { | ||||
|                             ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); | ||||
|                             OC_WASM3_TRAP(app->env.m3Runtime, res, "Runtime error"); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | @ -664,7 +724,7 @@ i32 orca_runloop(void* user) | |||
|                             M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_DOWN], 1, args); | ||||
|                             if(res) | ||||
|                             { | ||||
|                                 ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); | ||||
|                                 OC_WASM3_TRAP(app->env.m3Runtime, res, "Runtime error"); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|  | @ -677,7 +737,7 @@ i32 orca_runloop(void* user) | |||
|                             M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_UP], 1, args); | ||||
|                             if(res) | ||||
|                             { | ||||
|                                 ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); | ||||
|                                 OC_WASM3_TRAP(app->env.m3Runtime, res, "Runtime error"); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|  | @ -692,7 +752,7 @@ i32 orca_runloop(void* user) | |||
|                         M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_WHEEL], 2, args); | ||||
|                         if(res) | ||||
|                         { | ||||
|                             ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); | ||||
|                             OC_WASM3_TRAP(app->env.m3Runtime, res, "Runtime error"); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | @ -706,7 +766,7 @@ i32 orca_runloop(void* user) | |||
|                         M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_MOVE], 4, args); | ||||
|                         if(res) | ||||
|                         { | ||||
|                             ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); | ||||
|                             OC_WASM3_TRAP(app->env.m3Runtime, res, "Runtime error"); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | @ -729,7 +789,7 @@ i32 orca_runloop(void* user) | |||
|                             M3Result res = m3_Call(exports[OC_EXPORT_KEY_DOWN], 2, args); | ||||
|                             if(res) | ||||
|                             { | ||||
|                                 ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); | ||||
|                                 OC_WASM3_TRAP(app->env.m3Runtime, res, "Runtime error"); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|  | @ -741,7 +801,7 @@ i32 orca_runloop(void* user) | |||
|                             M3Result res = m3_Call(exports[OC_EXPORT_KEY_UP], 2, args); | ||||
|                             if(res) | ||||
|                             { | ||||
|                                 ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); | ||||
|                                 OC_WASM3_TRAP(app->env.m3Runtime, res, "Runtime error"); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|  | @ -760,7 +820,7 @@ i32 orca_runloop(void* user) | |||
|             M3Result res = m3_Call(exports[OC_EXPORT_FRAME_REFRESH], 0, 0); | ||||
|             if(res) | ||||
|             { | ||||
|                 ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); | ||||
|                 OC_WASM3_TRAP(app->env.m3Runtime, res, "Runtime error"); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -923,7 +983,7 @@ i32 orca_runloop(void* user) | |||
|         M3Result res = m3_Call(exports[OC_EXPORT_TERMINATE], 0, 0); | ||||
|         if(res) | ||||
|         { | ||||
|             ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); | ||||
|             OC_WASM3_TRAP(app->env.m3Runtime, res, "Runtime error"); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -130,7 +130,15 @@ oc_runtime* oc_runtime_get(void); | |||
| oc_wasm_env* oc_runtime_get_env(void); | ||||
| oc_str8 oc_runtime_get_wasm_memory(void); | ||||
| 
 | ||||
| void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const char* function, int line, const char* msg); | ||||
| #define ORCA_WASM3_ABORT(runtime, err, msg) orca_wasm3_abort(runtime, err, __FILE__, __FUNCTION__, __LINE__, msg) | ||||
| void oc_abort_ext_dialog(const char* file, const char* function, int line, const char* fmt, ...); | ||||
| void oc_assert_fail_dialog(const char* file, const char* function, int line, const char* test, const char* fmt, ...); | ||||
| 
 | ||||
| #define _OC_ASSERT_DIALOG_(test, fmt, ...) \ | ||||
|     ((test) || (oc_assert_fail_dialog(__FILE__, __FUNCTION__, __LINE__, #test, fmt, ##__VA_ARGS__), 0)) | ||||
| #define OC_ASSERT_DIALOG(test, ...) \ | ||||
|     _OC_ASSERT_DIALOG_(test, OC_VA_NOPT("", ##__VA_ARGS__) OC_ARG1(__VA_ARGS__) OC_VA_COMMA_TAIL(__VA_ARGS__)) | ||||
| 
 | ||||
| void oc_wasm3_trap(IM3Runtime runtime, M3Result res, const char* file, const char* function, int line, const char* msg); | ||||
| #define OC_WASM3_TRAP(runtime, err, msg) oc_wasm3_trap(runtime, err, __FILE__, __FUNCTION__, __LINE__, msg) | ||||
| 
 | ||||
| #endif //__RUNTIME_H_
 | ||||
|  |  | |||
|  | @ -151,13 +151,13 @@ oc_wasm_addr oc_wasm_arena_push(oc_wasm_addr arena, u64 size) | |||
|     M3Result res = m3_Call(env->exports[OC_EXPORT_ARENA_PUSH], 2, args); | ||||
|     if(res) | ||||
|     { | ||||
|         ORCA_WASM3_ABORT(env->m3Runtime, res, "Runtime error"); | ||||
|         OC_WASM3_TRAP(env->m3Runtime, res, "Runtime error"); | ||||
|     } | ||||
| 
 | ||||
|     res = m3_GetResults(env->exports[OC_EXPORT_ARENA_PUSH], 1, retPointers); | ||||
|     if(res) | ||||
|     { | ||||
|         ORCA_WASM3_ABORT(env->m3Runtime, res, "Runtime error"); | ||||
|         OC_WASM3_TRAP(env->m3Runtime, res, "Runtime error"); | ||||
|     } | ||||
| 
 | ||||
|     return (retValues[0]); | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ | |||
| }, | ||||
| { | ||||
| 	"name": "oc_bridge_assert_fail", | ||||
| 	"cname": "oc_assert_fail", | ||||
| 	"cname": "oc_assert_fail_dialog", | ||||
| 	"ret": {"name": "void", "tag": "v"}, | ||||
| 	"args": [ {"name": "file", | ||||
| 			   "type": {"name": "const char*", "tag": "p"}, | ||||
|  | @ -53,7 +53,7 @@ | |||
| }, | ||||
| { | ||||
| 	"name": "oc_bridge_abort_ext", | ||||
| 	"cname": "oc_abort_ext", | ||||
| 	"cname": "oc_abort_ext_dialog", | ||||
| 	"ret": {"name": "void", "tag": "v"}, | ||||
| 	"args": [ {"name": "file", | ||||
| 			   "type": {"name": "const char*", "tag": "p"}, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue