aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormoteus <mimir@newmail.ru>2013-12-26 15:34:58 +0400
committermoteus <mimir@newmail.ru>2013-12-26 15:34:58 +0400
commit5982fd74baad6cdee2c536203afe6c435a2d02e9 (patch)
treee8b7e667ab4160ad95e9409bc7bd826e69fbc9ff
parent92ec624951de2d344b28eb5262a3534822f6d6a7 (diff)
downloadlua-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.md20
-rw-r--r--src/llthread.c43
2 files changed, 54 insertions, 9 deletions
diff --git a/README.md b/README.md
index c0b67bf..3721b90 100644
--- a/README.md
+++ b/README.md
@@ -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[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/moteus/lua-llthreads2/trend.png)](https://bitdeli.com/free "Bitdeli Badge") 20[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/moteus/lua-llthreads2/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
20 21
22
23##Usage
24
25### Use custom logger
26In this example I use [lua-log](https://github.com/moteus/lua-log) library.
27``` Lua
28-- This is child thread.
29local llthreads = require "llthreads"
30-- Send logs using ZMQ
31local LOG = require"log".new(
32 require "log.writer.net.zmq".new("tcp://127.0.0.1:5555")
33)
34llthread.set_logger(function(msg) LOG.error(msg) end)
35
36...
37
38-- This error with traceback will be passed to logger
39error("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
63LLTHREADS_EXPORT_API int luaopen_llthreads(lua_State *L); 63LLTHREADS_EXPORT_API int luaopen_llthreads(lua_State *L);
64 64
65#define LLTHREAD_T_NAME "LLThread"
66static const char *LLTHREAD_T = LLTHREAD_T_NAME;
67static 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
316void 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
313static void open_thread_libs(lua_State *L){ 337static 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"
547static const char *LLTHREAD_T = LLTHREAD_T_NAME;
548
549static llthread_t *l_llthread_at (lua_State *L, int i) { 568static 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
698static 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
681static const struct luaL_Reg l_llthreads_lib[] = { 705static 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};