From d8e446dfad1195d0ed3a63e8945a2f96c73f84cc Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Tue, 5 Jun 2012 21:15:02 +0200 Subject: * fixed thread_cancel() not working when called without argument * new lane-global function set_error_reporting() to enable more data detailed data provided by lane_error() --- CHANGES | 4 +- docs/index.html | 16 ++++-- src/lanes.c | 168 ++++++++++++++++++++++++++++++++++++++------------------ 3 files changed, 130 insertions(+), 58 deletions(-) diff --git a/CHANGES b/CHANGES index d9f2641..ed8e317 100644 --- a/CHANGES +++ b/CHANGES @@ -1,7 +1,9 @@ CHANGES: -CHANGE X: +CHANGE 37: BGe 4-Jun-2012 (fix and idea courtesy of sonoro1234) + * fixed thread_cancel() not working when called without argument + * new lane-global function set_error_reporting() to enable more data detailed data provided by lane_error() CHANGE 36 BGe 26-Apr-2012 * improved LuaJIT2 compatibility by handling "*" library set through luaL_openlibs() diff --git a/docs/index.html b/docs/index.html index 5fe992d..1aeffe9 100644 --- a/docs/index.html +++ b/docs/index.html @@ -56,7 +56,7 @@


Copyright © 2007-12 Asko Kauppi, Benoit Germain. All rights reserved.
Lua Lanes is published under the same MIT license as Lua 5.1. -

This document was revised on 17-Feb-11, and applies to version 3.1.0 +

This document was revised on 17-Feb-11, and applies to version 3.1.2

@@ -431,9 +431,17 @@ Returns nil on timeout, nil,err,stack_tbl if the lane hit an e or the return values of the lane. Unlike in reading the results in table fashion, errors are not propagated.

-stack_tbl is an array of "<filename>:<line>" strings, -describing where the error was thrown. Use table.concat() to format -it to your liking (or just ignore it). + +
+ set_error_reporting("basic"|"extended") +
+

+ Sets the error reporting mode. "basic" is selected by default. +

+ stack_tbl is a table describing where the error was thrown.
+ In extended mode, stack_tbl is an array of tables containing info gathered with lua_getinfo() ("source","currentline","name","namewhat","what").
+In "basic mode", stack_tbl is an array of "<filename>:<line>" strings. Use table.concat() to format it to your liking (or just ignore it). +

If you use :join, make sure your lane main function returns a non-nil value so you can tell timeout and error cases apart from succesful diff --git a/src/lanes.c b/src/lanes.c index 176009a..d777be1 100644 --- a/src/lanes.c +++ b/src/lanes.c @@ -51,7 +51,7 @@ * ... */ -char const* VERSION = "3.1.1"; +char const* VERSION = "3.1.2"; /* =============================================================================== @@ -107,10 +107,6 @@ THE SOFTWARE. */ #define ERROR_FULL_STACK -#ifdef ERROR_FULL_STACK -# define STACK_TRACE_KEY ((void*)lane_error) // used as registry key -#endif - // NOTE: values to be changed by either thread, during execution, without // locking, are marked "volatile" // @@ -695,10 +691,11 @@ LUAG_FUNC( linda_deep ) { LUAG_FUNC( linda_tostring) { char text[32]; - struct s_Linda *linda = lua_toLinda( L, 1); + int len; + struct s_Linda* linda = lua_toLinda( L, 1); luaL_argcheck( L, linda, 1, "expected a linda object!"); - sprintf( text, "linda: %p", linda); - lua_pushstring( L, text); + len = sprintf( text, "linda: %p", linda); + lua_pushlstring( L, text, len); return 1; } @@ -720,15 +717,15 @@ LUAG_FUNC( linda_concat) if ( linda1) { char text[32]; - sprintf( text, "linda: %p", linda1); - lua_pushstring( L, text); + int len = sprintf( text, "linda: %p", linda1); + lua_pushlstring( L, text, len); lua_replace( L, 1); } if ( linda2) { char text[32]; - sprintf( text, "linda: %p", linda2); - lua_pushstring( L, text); + int len = sprintf( text, "linda: %p", linda2); + lua_pushlstring( L, text, len); lua_replace( L, 2); } // concat the result @@ -1281,58 +1278,118 @@ LUAG_FUNC( _single ) { */ #ifdef ERROR_FULL_STACK -static int lane_error( lua_State *L ) { - lua_Debug ar; - unsigned lev,n; +# define STACK_TRACE_KEY ((void*)lane_error) // used as registry key +# define EXTENDED_STACK_TRACE_KEY ((void*)LG_set_error_reporting) // used as registry key + +#ifdef ERROR_FULL_STACK +LUAG_FUNC( set_error_reporting) +{ + bool_t equal; + luaL_checktype( L, 1, LUA_TSTRING); + lua_pushliteral( L, "extended"); + equal = lua_rawequal( L, -1, 1); + lua_pop( L, 1); + if( equal) + { + goto done; + } + lua_pushliteral( L, "basic"); + equal = !lua_rawequal( L, -1, 1); + lua_pop( L, 1); + if( equal) + { + return luaL_error( L, "unsupported error reporting model"); + } +done: + lua_pushlightuserdata( L, EXTENDED_STACK_TRACE_KEY); + lua_pushboolean( L, equal); + lua_rawset( L, LUA_REGISTRYINDEX); + return 0; +} +#endif // ERROR_FULL_STACK + +static int lane_error( lua_State* L) +{ + lua_Debug ar; + unsigned lev, n; + bool_t extended; - // [1]: error message (any type) + // [1]: error message (any type) - assert( lua_gettop(L)==1 ); + assert( lua_gettop( L) == 1); - // Don't do stack survey for cancelled lanes. - // + // Don't do stack survey for cancelled lanes. + // #if 1 - if (lua_touserdata(L,1) == CANCEL_ERROR) - return 1; // just pass on + if( lua_touserdata( L, 1) == CANCEL_ERROR) + return 1; // just pass on #endif - // Place stack trace at 'registry[lane_error]' for the 'luc_pcall()' - // caller to fetch. This bypasses the Lua 5.1 limitation of only one - // return value from error handler to 'lua_pcall()' caller. + lua_pushlightuserdata( L, EXTENDED_STACK_TRACE_KEY); + lua_gettable( L, LUA_REGISTRYINDEX); + extended = lua_toboolean( L, -1); + lua_pop( L, 1); - // It's adequate to push stack trace as a table. This gives the receiver - // of the stack best means to format it to their liking. Also, it allows - // us to add more stack info later, if needed. - // - // table of { "sourcefile.lua:", ... } - // - STACK_GROW(L,3); - lua_newtable(L); + // Place stack trace at 'registry[lane_error]' for the 'lua_pcall()' + // caller to fetch. This bypasses the Lua 5.1 limitation of only one + // return value from error handler to 'lua_pcall()' caller. - // Best to start from level 1, but in some cases it might be a C function - // and we don't get '.currentline' for that. It's okay - just keep level - // and table index growing separate. --AKa 22-Jan-2009 - // - lev= 0; - n=1; - while( lua_getstack(L, ++lev, &ar ) ) { - lua_getinfo(L, "Sl", &ar); - if (ar.currentline > 0) { - lua_pushinteger( L, n++ ); - lua_pushfstring( L, "%s:%d", ar.short_src, ar.currentline ); - lua_settable( L, -3 ); - } - } + // It's adequate to push stack trace as a table. This gives the receiver + // of the stack best means to format it to their liking. Also, it allows + // us to add more stack info later, if needed. + // + // table of { "sourcefile.lua:", ... } + // + STACK_GROW( L, 4); + lua_newtable( L); + + // Best to start from level 1, but in some cases it might be a C function + // and we don't get '.currentline' for that. It's okay - just keep level + // and table index growing separate. --AKa 22-Jan-2009 + // + lev = 0; + n = 1; + while( lua_getstack( L, ++ lev, &ar)) + { + lua_getinfo( L, extended ? "Sln" : "Sl", &ar); + if( extended) + { + lua_newtable( L); + + lua_pushstring( L, ar.source); + lua_setfield( L, -2, "source"); - lua_pushlightuserdata( L, STACK_TRACE_KEY ); - lua_insert(L,-2); - lua_settable( L, LUA_REGISTRYINDEX ); + lua_pushinteger( L, ar.currentline); + lua_setfield( L, -2, "currentline"); - assert( lua_gettop(L)== 1 ); + lua_pushstring( L, ar.name); + lua_setfield( L, -2, "name"); - return 1; // the untouched error value + lua_pushstring( L, ar.namewhat); + lua_setfield( L, -2, "namewhat"); + + lua_pushstring( L, ar.what); + lua_setfield( L, -2, "what"); + + lua_rawseti(L, -2, n ++); + } + else if (ar.currentline > 0) + { + lua_pushinteger( L, n++ ); + lua_pushfstring( L, "%s:%d", ar.short_src, ar.currentline ); + lua_settable( L, -3 ); + } + } + + lua_pushlightuserdata( L, STACK_TRACE_KEY); + lua_insert( L ,-2); + lua_settable( L, LUA_REGISTRYINDEX); + + assert( lua_gettop( L) == 1); + + return 1; // the untouched error value } -#endif +#endif // ERROR_FULL_STACK #if defined PLATFORM_WIN32 && !defined __GNUC__ //see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx @@ -1408,6 +1465,11 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs) lua_setglobal( L, "cancel_test" ); #ifdef ERROR_FULL_STACK + // Tie "set_error_reporting()" to the state + // + lua_pushcfunction( L, LG_set_error_reporting); + lua_setglobal( L, "set_error_reporting"); + STACK_GROW( L, 1 ); lua_pushcfunction( L, lane_error ); lua_insert( L, 1 ); @@ -1885,7 +1947,7 @@ static bool_t thread_cancel( struct s_lane *s, double secs, bool_t force) LUAG_FUNC( thread_cancel) { - if( lua_gettop( L) != 1 || lua_type( L, 1) != LUA_TUSERDATA) + if( lua_gettop( L) < 1 || lua_type( L, 1) != LUA_TUSERDATA) { return luaL_error( L, "invalid argument #1, did you use ':' as you should?"); } -- cgit v1.2.3-55-g6feb