From 93643adaa38418bf3656cd92a71768fbab59b984 Mon Sep 17 00:00:00 2001 From: Konstantin Osipov <kostja@tarantool.org> Date: Fri, 13 Jul 2012 00:12:45 +0400 Subject: [PATCH] Fix a regression with nested @finally introduced with a new runtime. Fix a regression with nested @finally not being called, introduced in 1.4.7 release. Big thanks to David Chisnall for a swift fix in GNUStep Objective C runtime. Add unit tests for two Objective C runtime properties: nested finally handling and ability to catch C++ exceptions. --- .gitignore | 2 ++ test/unit/CMakeLists.txt | 7 +++++ test/unit/objc_catchcxx.m | 15 +++++++++ test/unit/objc_catchcxx.result | 1 + test/unit/objc_catchcxx.test | 1 + test/unit/objc_finally.m | 46 ++++++++++++++++++++++++++++ test/unit/objc_finally.result | 5 +++ test/unit/objc_finally.test | 1 + third_party/libobjc/eh_personality.c | 3 +- 9 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 test/unit/objc_catchcxx.m create mode 100644 test/unit/objc_catchcxx.result create mode 100644 test/unit/objc_catchcxx.test create mode 100644 test/unit/objc_finally.m create mode 100644 test/unit/objc_finally.result create mode 100644 test/unit/objc_finally.test diff --git a/.gitignore b/.gitignore index b93343473a..6e433cc0ce 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,8 @@ test/box/protocol test/box/connector test/unit/queue test/unit/mhash +test/unit/objc_finally +test/unit/objc_catchcxx Makefile CMakeFiles CMakeCache.txt diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 6154fc20a4..7d3a49f43b 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -1,3 +1,10 @@ add_executable(queue queue.c) add_executable(mhash mhash.c) +add_executable(objc_finally objc_finally.m) +add_executable(objc_catchcxx objc_catchcxx.m) set_target_properties(mhash PROPERTIES COMPILE_FLAGS "-std=c99") +target_link_libraries(objc_finally ${LIBOBJC_LIB}) +target_link_libraries(objc_catchcxx ${LIBOBJC_LIB} ${LUAJIT_LIB}) +if (TARGET_OS_LINUX OR TARGET_OS_DEBIAN_FREEBSD) + target_link_libraries(objc_catchcxx dl) +endif() diff --git a/test/unit/objc_catchcxx.m b/test/unit/objc_catchcxx.m new file mode 100644 index 0000000000..b90e53092b --- /dev/null +++ b/test/unit/objc_catchcxx.m @@ -0,0 +1,15 @@ +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" + +int main() +{ + lua_State *L = luaL_newstate(); + luaL_openlibs(L); + @try { + luaL_error(L, "test"); + } @catch (...) { + printf("exception handled\n"); + } + lua_close(L); +} diff --git a/test/unit/objc_catchcxx.result b/test/unit/objc_catchcxx.result new file mode 100644 index 0000000000..761f3a2040 --- /dev/null +++ b/test/unit/objc_catchcxx.result @@ -0,0 +1 @@ +exception handled diff --git a/test/unit/objc_catchcxx.test b/test/unit/objc_catchcxx.test new file mode 100644 index 0000000000..13f381fcb7 --- /dev/null +++ b/test/unit/objc_catchcxx.test @@ -0,0 +1 @@ +run_test("objc_catchcxx") diff --git a/test/unit/objc_finally.m b/test/unit/objc_finally.m new file mode 100644 index 0000000000..18cf5c62b5 --- /dev/null +++ b/test/unit/objc_finally.m @@ -0,0 +1,46 @@ +#include <stdio.h> +#include <objc/Object.h> +#include <objc/runtime.h> + +@interface Exception: Object { +} ++ (id) new; +@end + +@implementation Exception ++ (id) new +{ + return class_createInstance(self, 0); +} +@end + +void +throw_exception(void) +{ + printf("throw\n"); + @throw [Exception new]; +} + +void +test(void) +{ + @try { + throw_exception(); + } @finally { + printf("internal finally\n"); + } +} + +int +main(int ac, char **av) +{ + printf("start\n"); + @try { + test(); + } @catch(id e) { + printf("catch\n"); + } @finally { + printf("external finally\n"); + } + return 0; +} diff --git a/test/unit/objc_finally.result b/test/unit/objc_finally.result new file mode 100644 index 0000000000..1d09f8b413 --- /dev/null +++ b/test/unit/objc_finally.result @@ -0,0 +1,5 @@ +start +throw +internal finally +catch +external finally diff --git a/test/unit/objc_finally.test b/test/unit/objc_finally.test new file mode 100644 index 0000000000..65770394cc --- /dev/null +++ b/test/unit/objc_finally.test @@ -0,0 +1 @@ +run_test("objc_finally") diff --git a/third_party/libobjc/eh_personality.c b/third_party/libobjc/eh_personality.c index e3e4ead29c..77feb2a271 100644 --- a/third_party/libobjc/eh_personality.c +++ b/third_party/libobjc/eh_personality.c @@ -204,7 +204,7 @@ static handler_type check_action_record(struct _Unwind_Context *context, Class thrown_class, unsigned long *selector) { - //if (!action_record) { return handler_cleanup; } + if (!action_record) { return handler_cleanup; } while (action_record) { int filter = read_sleb128(&action_record); @@ -343,6 +343,7 @@ BEGIN_PERSONALITY_FUNCTION(__gnu_objc_personality_v0) action = dwarf_eh_find_callsite(context, &lsda); handler_type handler = check_action_record(context, foreignException, &lsda, action.action_record, thrown_class, &selector); + fprintf(stderr, "handler: %d\n", handler); // If there's no action record, we've only found a cleanup, so keep // searching for something real if (handler == handler_class || -- GitLab