From dc334a0c005ca2e806b88aec4b353e37cdb76665 Mon Sep 17 00:00:00 2001 From: Konstantin Osipov <kostja.osipov@gmail.com> Date: Thu, 18 Aug 2011 15:32:18 +0400 Subject: [PATCH] Update libcoro to 6.06. Fix a bug with error propagation in Lua. Fix a bug when Tarantool exceptions were intercepted by Lua in lua_pcall(), and converted to Lua errors. Let Tarantool exceptions pass freely through Lua, by using lua_call() instead of lua_pcall(). In case of any Lua error lua_call() aborts execution of the entire process. Register lua_atpanic that converts lua errors to Tarantool exception ER_PROC_LUA. Unwinding the stack in this manner didn't work properly with libcoro 6.0, which we were using. Update libcoro library to version 6.06 to fix this problem. --- mod/box/box_lua.m | 12 ++- test/box/lua.result | 2 + test/box/lua.test | 2 +- third_party/coro/coro.c | 177 ++++++++++++++++++++++++---------------- third_party/coro/coro.h | 34 ++++++-- 5 files changed, 146 insertions(+), 81 deletions(-) diff --git a/mod/box/box_lua.m b/mod/box/box_lua.m index a1f9877e39..15be32b21c 100644 --- a/mod/box/box_lua.m +++ b/mod/box/box_lua.m @@ -112,6 +112,13 @@ void box_lua_find(lua_State *L, const char *name, const char *name_end) } +static int +box_lua_panic(struct lua_State *L) +{ + tnt_raise(ClientError, :ER_PROC_LUA, lua_tostring(L, -1)); + return 0; +} + /** * Invoke a Lua stored procedure from the binary protocol * (implementation of 'CALL' command code). @@ -130,9 +137,7 @@ void box_lua_call(struct box_txn *txn __attribute__((unused)), /* Push the rest of args (a tuple) as is. */ lua_pushlstring(L, data->data, data->len); - int r = lua_pcall(L, 1, 0, 0); - if (r) - tnt_raise(ClientError, :ER_PROC_LUA, lua_tostring(L, -1)); + lua_call(L, 1, LUA_MULTRET); } @finally { /* * Allow the used coro to be garbage collected. @@ -146,6 +151,7 @@ struct lua_State * mod_lua_init(struct lua_State *L) { luaL_register(L, "box", boxlib); + lua_atpanic(L, box_lua_panic); return L; } diff --git a/test/box/lua.result b/test/box/lua.result index 62d215f476..ba9dcb4d60 100644 --- a/test/box/lua.result +++ b/test/box/lua.result @@ -80,3 +80,5 @@ error: '[string "box.process(22, box.pack(''iii'', 0, 0, 0))"]:1: box.process(CA ... call box.process('abc', 'def') An error occurred: ER_PROC_LUA, 'Lua error: bad argument #1 to '?' (number expected, got string)�' +call box.pack('test') +An error occurred: ER_PROC_LUA, 'Lua error: box.pack: unsupported pack format specifier ''�' diff --git a/test/box/lua.test b/test/box/lua.test index c8676bf5ce..38b24311a8 100644 --- a/test/box/lua.test +++ b/test/box/lua.test @@ -29,4 +29,4 @@ exec admin "lua box.process(21, box.pack('iiip', 0, 1, 1, box.pack('i', 1)))" exec admin "lua box.process(17, box.pack('iiiiiip', 0, 0, 0, 2^31, 1, 1, box.pack('i', 1)))" exec admin "lua box.process(22, box.pack('iii', 0, 0, 0))" exec sql "call box.process('abc', 'def')" - +exec sql "call box.pack('test')" diff --git a/third_party/coro/coro.c b/third_party/coro/coro.c index ff41ffd186..615af8362c 100644 --- a/third_party/coro/coro.c +++ b/third_party/coro/coro.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2009 Marc Alexander Lehmann <schmorp@schmorp.de> + * Copyright (c) 2001-2011 Marc Alexander Lehmann <schmorp@schmorp.de> * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: @@ -88,6 +88,10 @@ coro_init (void) coro_transfer (new_coro, create_coro); +#if __GCC_HAVE_DWARF2_CFI_ASM && __amd64 + asm (".cfi_undefined rip"); +#endif + func ((void *)arg); /* the new coro returned. bad. just abort() for now */ @@ -112,73 +116,87 @@ trampoline (int sig) # if CORO_ASM + #if _WIN32 + #define CORO_WIN_TIB 1 + #endif + asm ( - ".text\n" - ".globl coro_transfer\n" - ".type coro_transfer, @function\n" + "\t.text\n" + "\t.globl coro_transfer\n" "coro_transfer:\n" + /* windows, of course, gives a shit on the amd64 ABI and uses different registers */ + /* http://blogs.msdn.com/freik/archive/2005/03/17/398200.aspx */ #if __amd64 - #define NUM_SAVED 6 - "\tpush %rbp\n" - "\tpush %rbx\n" - "\tpush %r12\n" - "\tpush %r13\n" - "\tpush %r14\n" - "\tpush %r15\n" - "\tmov %rsp, (%rdi)\n" - "\tmov (%rsi), %rsp\n" - "\tpop %r15\n" - "\tpop %r14\n" - "\tpop %r13\n" - "\tpop %r12\n" - "\tpop %rbx\n" - "\tpop %rbp\n" + #ifdef WIN32 + /* TODO: xmm6..15 also would need to be saved. sigh. */ + #define NUM_SAVED 8 + "\tpushq %rsi\n" + "\tpushq %rdi\n" + "\tpushq %rbp\n" + "\tpushq %rbx\n" + "\tpushq %r12\n" + "\tpushq %r13\n" + "\tpushq %r14\n" + "\tpushq %r15\n" + #if CORO_WIN_TIB + "\tpushq %fs:0x0\n" + "\tpushq %fs:0x8\n" + "\tpushq %fs:0xc\n" + #endif + "\tmovq %rsp, (%rcx)\n" + "\tmovq (%rdx), %rsp\n" + #if CORO_WIN_TIB + "\tpopq %fs:0xc\n" + "\tpopq %fs:0x8\n" + "\tpopq %fs:0x0\n" + #endif + "\tpopq %r15\n" + "\tpopq %r14\n" + "\tpopq %r13\n" + "\tpopq %r12\n" + "\tpopq %rbx\n" + "\tpopq %rbp\n" + "\tpopq %rdi\n" + "\tpopq %rsi\n" + #else + #define NUM_SAVED 6 + "\tpushq %rbp\n" + "\tpushq %rbx\n" + "\tpushq %r12\n" + "\tpushq %r13\n" + "\tpushq %r14\n" + "\tpushq %r15\n" + "\tmovq %rsp, (%rdi)\n" + "\tmovq (%rsi), %rsp\n" + "\tpopq %r15\n" + "\tpopq %r14\n" + "\tpopq %r13\n" + "\tpopq %r12\n" + "\tpopq %rbx\n" + "\tpopq %rbp\n" + #endif #elif __i386 #define NUM_SAVED 4 - "\tpush %ebp\n" - "\tpush %ebx\n" - "\tpush %esi\n" - "\tpush %edi\n" - "\tmov %esp, (%eax)\n" - "\tmov (%edx), %esp\n" - "\tpop %edi\n" - "\tpop %esi\n" - "\tpop %ebx\n" - "\tpop %ebp\n" - #else - #error unsupported architecture - #endif - "\tret\n" - ); - asm ( - ".text\n" - ".globl coro_save_and_longjmp\n" - ".type coro_save_and_longjmp, @function\n" - "coro_save_and_longjmp:\n" - #if __amd64 - #define NUM_SAVED 6 - "\tpush %rbp\n" - "\tpush %rbx\n" - "\tpush %r12\n" - "\tpush %r13\n" - "\tpush %r14\n" - "\tpush %r15\n" - "\tmov %rsp, (%rdi)\n" - "\tmovq %rsi, %rdi\n" - "\tsubq $8, %rsp\n" - "\tmovl %edx, %esi\n" - "\tcall longjmp\n" - #elif __i386 - #define NUM_SAVED 4 - "\tpush %ebp\n" - "\tpush %ebx\n" - "\tpush %esi\n" - "\tpush %edi\n" - "\tmov %esp, (%eax)\n" - "\tsubl $0x28,%esp\n" - "\tmovl %ecx,0x4(%esp)\n" - "\tmovl %edx,(%esp)\n" - "\tcall longjmp\n" + "\tpushl %ebp\n" + "\tpushl %ebx\n" + "\tpushl %esi\n" + "\tpushl %edi\n" + #if CORO_WIN_TIB + "\tpushl %fs:0\n" + "\tpushl %fs:4\n" + "\tpushl %fs:8\n" + #endif + "\tmovl %esp, (%eax)\n" + "\tmovl (%edx), %esp\n" + #if CORO_WIN_TIB + "\tpopl %fs:8\n" + "\tpopl %fs:4\n" + "\tpopl %fs:0\n" + #endif + "\tpopl %edi\n" + "\tpopl %esi\n" + "\tpopl %ebx\n" + "\tpopl %ebp\n" #else #error unsupported architecture #endif @@ -224,8 +242,8 @@ coro_create (coro_context *ctx, coro_func coro, void *arg, void *sptr, long ssiz } /* set the new stack */ - nstk.ss_sp = STACK_ADJUST_PTR (sptr,ssize); /* yes, some platforms (IRIX) get this wrong. */ - nstk.ss_size = STACK_ADJUST_SIZE (sptr,ssize); + nstk.ss_sp = STACK_ADJUST_PTR (sptr, ssize); /* yes, some platforms (IRIX) get this wrong. */ + nstk.ss_size = STACK_ADJUST_SIZE (sptr, ssize); nstk.ss_flags = 0; if (sigaltstack (&nstk, &ostk) < 0) @@ -259,9 +277,12 @@ coro_create (coro_context *ctx, coro_func coro, void *arg, void *sptr, long ssiz # elif CORO_LOSER coro_setjmp (ctx->env); - #if __CYGWIN__ + #if __CYGWIN__ && __i386 ctx->env[8] = (long) coro_init; ctx->env[7] = (long) ((char *)sptr + ssize) - sizeof (long); + #elif __CYGWIN__ && __x86_64 + ctx->env[7] = (long) coro_init; + ctx->env[6] = (long) ((char *)sptr + ssize) - sizeof (long); #elif defined(__MINGW32__) ctx->env[5] = (long) coro_init; ctx->env[4] = (long) ((char *)sptr + ssize) - sizeof (long); @@ -270,10 +291,10 @@ coro_create (coro_context *ctx, coro_func coro, void *arg, void *sptr, long ssiz ((_JUMP_BUFFER *)&ctx->env)->Esp = (long) STACK_ADJUST_PTR (sptr, ssize) - sizeof (long); #elif defined(_M_AMD64) ((_JUMP_BUFFER *)&ctx->env)->Rip = (__int64) coro_init; - ((_JUMP_BUFFER *)&ctx->env)->Rsp = (__int64) STACK_ADJUST_PTR (sptr, ssize) - sizeof (long); + ((_JUMP_BUFFER *)&ctx->env)->Rsp = (__int64) STACK_ADJUST_PTR (sptr, ssize) - sizeof (__int64); #elif defined(_M_IA64) ((_JUMP_BUFFER *)&ctx->env)->StIIP = (__int64) coro_init; - ((_JUMP_BUFFER *)&ctx->env)->IntSp = (__int64) STACK_ADJUST_PTR (sptr, ssize) - sizeof (long); + ((_JUMP_BUFFER *)&ctx->env)->IntSp = (__int64) STACK_ADJUST_PTR (sptr, ssize) - sizeof (__int64); #else #error "microsoft libc or architecture not supported" #endif @@ -306,12 +327,20 @@ coro_create (coro_context *ctx, coro_func coro, void *arg, void *sptr, long ssiz # elif CORO_ASM ctx->sp = (void **)(ssize + (char *)sptr); - *--ctx->sp = (void *)0xdeadbeef; /* needed for alignment only */ + *--ctx->sp = (void *)abort; /* needed for alignment only */ *--ctx->sp = (void *)coro_init; + + #if CORO_WIN_TIB + *--ctx->sp = 0; /* ExceptionList */ + *--ctx->sp = (char *)sptr + ssize; /* StackBase */ + *--ctx->sp = sptr; /* StackLimit */ + #endif + ctx->sp -= NUM_SAVED; + memset (ctx->sp, 0, sizeof (*ctx->sp) * NUM_SAVED); # elif CORO_UCONTEXT - + getcontext (&(ctx->uc)); ctx->uc.uc_link = 0; @@ -406,7 +435,15 @@ coro_create (coro_context *ctx, coro_func coro, void *arg, void *sptr, long ssiz args.main = &nctx; pthread_attr_init (&attr); +#if __UCLIBC__ + /* exists, but is borked */ + /*pthread_attr_setstacksize (&attr, (size_t)ssize);*/ +#elif __CYGWIN__ + /* POSIX, not here */ + pthread_attr_setstacksize (&attr, (size_t)ssize); +#else pthread_attr_setstack (&attr, sptr, (size_t)ssize); +#endif pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS); pthread_create (&ctx->id, &attr, coro_init, &args); diff --git a/third_party/coro/coro.h b/third_party/coro/coro.h index 792d3f8dd7..52bb4280d3 100644 --- a/third_party/coro/coro.h +++ b/third_party/coro/coro.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2009 Marc Alexander Lehmann <schmorp@schmorp.de> + * Copyright (c) 2001-2011 Marc Alexander Lehmann <schmorp@schmorp.de> * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: @@ -69,11 +69,21 @@ * 2008-11-16 work around a freebsd pthread bug. * 2008-11-19 define coro_*jmp symbols for easier porting. * 2009-06-23 tentative win32-backend support for mingw32 (Yasuhiro Matsumoto). + * 2010-12-03 tentative support for uclibc (which lacks all sorts of things). + * 2011-05-30 set initial callee-saved-registers to zero with CORO_ASM. + * use .cfi_undefined rip on linux-amd64 for better backtraces. + * 2011-06-08 maybe properly implement weird windows amd64 calling conventions. + * 2011-07-03 rely on __GCC_HAVE_DWARF2_CFI_ASM for cfi detection. + * 2011-08-08 cygwin trashes stacks, use pthreads with double stack on cygwin. */ #ifndef CORO_H #define CORO_H +#if __cplusplus +extern "C" { +#endif + #define CORO_VERSION 2 /* @@ -199,7 +209,17 @@ void coro_destroy (coro_context *ctx); && !defined(CORO_SJLJ) && !defined(CORO_LINUX) \ && !defined(CORO_IRIX) && !defined(CORO_ASM) \ && !defined(CORO_PTHREAD) -#error unknown or unsupported architecture +# if defined(WINDOWS) || defined(_WIN32) +# define CORO_LOSER 1 /* you don't win with windoze */ +# elif defined(__linux) && (defined(__x86) || defined (__amd64)) +# define CORO_ASM 1 +# elif defined(HAVE_UCONTEXT_H) +# define CORO_UCONTEXT 1 +# elif defined(HAVE_SETJMP_H) && defined(HAVE_SIGALTSTACK) +# define CORO_SJLJ 1 +# else +error unknown or unsupported architecture +# endif #endif /*****************************************************************************/ @@ -256,16 +276,12 @@ struct coro_context { #elif CORO_ASM -# include <setjmp.h> /* for jmp_buf */ - struct coro_context { void **sp; /* must be at offset 0 */ }; -void __attribute__ ((noinline, regparm(2))) +void __attribute__ ((__noinline__, __regparm__(2))) coro_transfer (coro_context *prev, coro_context *next); -void __attribute__ ((noinline, regparm(3))) -coro_save_and_longjmp (coro_context *prev, jmp_buf jump, int value); # define coro_destroy(ctx) (void *)(ctx) @@ -285,5 +301,9 @@ void coro_destroy (coro_context *ctx); #endif +#if __cplusplus +} +#endif + #endif -- GitLab