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