diff options
author | moteus <mimir@newmail.ru> | 2013-12-26 15:34:58 +0400 |
---|---|---|
committer | moteus <mimir@newmail.ru> | 2013-12-26 15:34:58 +0400 |
commit | 5982fd74baad6cdee2c536203afe6c435a2d02e9 (patch) | |
tree | e8b7e667ab4160ad95e9409bc7bd826e69fbc9ff | |
parent | 92ec624951de2d344b28eb5262a3534822f6d6a7 (diff) | |
download | lua-llthreads2-5982fd74baad6cdee2c536203afe6c435a2d02e9.tar.gz lua-llthreads2-5982fd74baad6cdee2c536203afe6c435a2d02e9.tar.bz2 lua-llthreads2-5982fd74baad6cdee2c536203afe6c435a2d02e9.zip |
Add. set_logger function allow logging errors (crash Lua VM) in current llthread's threads.
``` Lua
local llthreads = require "llthreads"
local LOG = require"log".new(
require "log.writer.net.zmq".new("tcp://127.0.0.1:5555")
)
llthread.set_logger(function(msg) LOG.error(msg) end)
```
-rw-r--r-- | README.md | 20 | ||||
-rw-r--r-- | src/llthread.c | 43 |
2 files changed, 54 insertions, 9 deletions
@@ -15,6 +15,26 @@ This is full dropin replacement for [llthreads](https://github.com/Neopallium/lu | |||
15 | ##Additional | 15 | ##Additional |
16 | * thread:join() method support zero timeout to check if thread alive | 16 | * thread:join() method support zero timeout to check if thread alive |
17 | * thread:join() method support arbitrary timeout on Windows platform | 17 | * thread:join() method support arbitrary timeout on Windows platform |
18 | * set_logger function allow logging errors (crash Lua VM) in current llthread's threads | ||
18 | 19 | ||
19 | [](https://bitdeli.com/free "Bitdeli Badge") | 20 | [](https://bitdeli.com/free "Bitdeli Badge") |
20 | 21 | ||
22 | |||
23 | ##Usage | ||
24 | |||
25 | ### Use custom logger | ||
26 | In this example I use [lua-log](https://github.com/moteus/lua-log) library. | ||
27 | ``` Lua | ||
28 | -- This is child thread. | ||
29 | local llthreads = require "llthreads" | ||
30 | -- Send logs using ZMQ | ||
31 | local LOG = require"log".new( | ||
32 | require "log.writer.net.zmq".new("tcp://127.0.0.1:5555") | ||
33 | ) | ||
34 | llthread.set_logger(function(msg) LOG.error(msg) end) | ||
35 | |||
36 | ... | ||
37 | |||
38 | -- This error with traceback will be passed to logger | ||
39 | error("SOME ERROR") | ||
40 | ``` | ||
diff --git a/src/llthread.c b/src/llthread.c index 0f43e14..0596b2a 100644 --- a/src/llthread.c +++ b/src/llthread.c | |||
@@ -62,6 +62,10 @@ typedef pthread_t os_thread_t; | |||
62 | 62 | ||
63 | LLTHREADS_EXPORT_API int luaopen_llthreads(lua_State *L); | 63 | LLTHREADS_EXPORT_API int luaopen_llthreads(lua_State *L); |
64 | 64 | ||
65 | #define LLTHREAD_T_NAME "LLThread" | ||
66 | static const char *LLTHREAD_T = LLTHREAD_T_NAME; | ||
67 | static const char *LLTHREAD_LOGGER_HOLDER = LLTHREAD_T_NAME " logger holder"; | ||
68 | |||
65 | //{ traceback | 69 | //{ traceback |
66 | 70 | ||
67 | #define ERROR_LEN 1024 | 71 | #define ERROR_LEN 1024 |
@@ -308,6 +312,26 @@ typedef struct llthread_t { | |||
308 | flags_t flags; | 312 | flags_t flags; |
309 | } llthread_t; | 313 | } llthread_t; |
310 | 314 | ||
315 | //{ logger interface | ||
316 | void llthread_log(lua_State *L, const char *hdr, const char *msg){ | ||
317 | int top = lua_gettop(L); | ||
318 | lua_rawgetp(L, LUA_REGISTRYINDEX, LLTHREAD_LOGGER_HOLDER); | ||
319 | if(lua_isnil(L, -1)){ | ||
320 | lua_pop(L, 1); | ||
321 | fputs(hdr, stderr); | ||
322 | fputs(msg, stderr); | ||
323 | fputc('\n', stderr); | ||
324 | fflush(stderr); | ||
325 | return; | ||
326 | } | ||
327 | lua_pushstring(L, hdr); | ||
328 | lua_pushstring(L, msg); | ||
329 | lua_concat(L, 2); | ||
330 | lua_pcall(L, 1, 0, 0); | ||
331 | lua_settop(L, top); | ||
332 | } | ||
333 | //} | ||
334 | |||
311 | //{ llthread_child | 335 | //{ llthread_child |
312 | 336 | ||
313 | static void open_thread_libs(lua_State *L){ | 337 | static void open_thread_libs(lua_State *L){ |
@@ -369,9 +393,7 @@ static OS_THREAD_RETURT llthread_child_thread_run(void *arg) { | |||
369 | 393 | ||
370 | /* alwasy print errors here, helps with debugging bad code. */ | 394 | /* alwasy print errors here, helps with debugging bad code. */ |
371 | if(this->status != 0) { | 395 | if(this->status != 0) { |
372 | const char *err_msg = lua_tostring(L, -1); | 396 | llthread_log(L, "Error from thread: ", lua_tostring(L, -1)); |
373 | fprintf(stderr, "Error from thread: %s\n", err_msg); | ||
374 | fflush(stderr); | ||
375 | } | 397 | } |
376 | 398 | ||
377 | /* if thread is detached, then destroy the child state. */ | 399 | /* if thread is detached, then destroy the child state. */ |
@@ -543,9 +565,6 @@ static llthread_t *llthread_create(lua_State *L, const char *code, size_t code_l | |||
543 | 565 | ||
544 | //{ Lua interface to llthread | 566 | //{ Lua interface to llthread |
545 | 567 | ||
546 | #define LLTHREAD_T_NAME "LLThread" | ||
547 | static const char *LLTHREAD_T = LLTHREAD_T_NAME; | ||
548 | |||
549 | static llthread_t *l_llthread_at (lua_State *L, int i) { | 568 | static llthread_t *l_llthread_at (lua_State *L, int i) { |
550 | llthread_t **this = (llthread_t **)lutil_checkudatap (L, i, LLTHREAD_T); | 569 | llthread_t **this = (llthread_t **)lutil_checkudatap (L, i, LLTHREAD_T); |
551 | luaL_argcheck (L, this != NULL, i, "thread expected"); | 570 | luaL_argcheck (L, this != NULL, i, "thread expected"); |
@@ -571,9 +590,7 @@ static int l_llthread_delete(lua_State *L) { | |||
571 | llthread_child_t *child = this->child; | 590 | llthread_child_t *child = this->child; |
572 | llthread_join(this, INFINITE_JOIN_TIMEOUT); | 591 | llthread_join(this, INFINITE_JOIN_TIMEOUT); |
573 | if(child && child->status != 0) { | 592 | if(child && child->status != 0) { |
574 | const char *err_msg = lua_tostring(child->L, -1); | 593 | llthread_log(child->L, "Error from non-joined thread: ", lua_tostring(child->L, -1)); |
575 | fprintf(stderr, "Error from non-joined thread: %s\n", err_msg); | ||
576 | fflush(stderr); | ||
577 | } | 594 | } |
578 | } | 595 | } |
579 | 596 | ||
@@ -678,8 +695,16 @@ static const struct luaL_Reg l_llthread_meth[] = { | |||
678 | 695 | ||
679 | //} | 696 | //} |
680 | 697 | ||
698 | static int l_llthread_set_logger(lua_State *L){ | ||
699 | lua_settop(L, 1); | ||
700 | luaL_argcheck(L, lua_isfunction(L, 1), 1, "function expected"); | ||
701 | lua_rawsetp(L, LUA_REGISTRYINDEX, LLTHREAD_LOGGER_HOLDER); | ||
702 | return 0; | ||
703 | } | ||
704 | |||
681 | static const struct luaL_Reg l_llthreads_lib[] = { | 705 | static const struct luaL_Reg l_llthreads_lib[] = { |
682 | {"new", l_llthread_new }, | 706 | {"new", l_llthread_new }, |
707 | {"set_logger", l_llthread_set_logger }, | ||
683 | 708 | ||
684 | {NULL, NULL} | 709 | {NULL, NULL} |
685 | }; | 710 | }; |