diff options
author | Benoit Germain <bnt.germain@gmail.com> | 2012-06-05 21:15:02 +0200 |
---|---|---|
committer | Benoit Germain <bnt.germain@gmail.com> | 2012-06-05 21:15:02 +0200 |
commit | d8e446dfad1195d0ed3a63e8945a2f96c73f84cc (patch) | |
tree | d475a5164d55a0633ff4ab64bbcda736ec3bd116 /src | |
parent | 1c33960abd867e425bad2633a85504f55a1f261c (diff) | |
download | lanes-d8e446dfad1195d0ed3a63e8945a2f96c73f84cc.tar.gz lanes-d8e446dfad1195d0ed3a63e8945a2f96c73f84cc.tar.bz2 lanes-d8e446dfad1195d0ed3a63e8945a2f96c73f84cc.zip |
* 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()
Diffstat (limited to 'src')
-rw-r--r-- | src/lanes.c | 168 |
1 files changed, 115 insertions, 53 deletions
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 @@ | |||
51 | * ... | 51 | * ... |
52 | */ | 52 | */ |
53 | 53 | ||
54 | char const* VERSION = "3.1.1"; | 54 | char const* VERSION = "3.1.2"; |
55 | 55 | ||
56 | /* | 56 | /* |
57 | =============================================================================== | 57 | =============================================================================== |
@@ -107,10 +107,6 @@ THE SOFTWARE. | |||
107 | */ | 107 | */ |
108 | #define ERROR_FULL_STACK | 108 | #define ERROR_FULL_STACK |
109 | 109 | ||
110 | #ifdef ERROR_FULL_STACK | ||
111 | # define STACK_TRACE_KEY ((void*)lane_error) // used as registry key | ||
112 | #endif | ||
113 | |||
114 | // NOTE: values to be changed by either thread, during execution, without | 110 | // NOTE: values to be changed by either thread, during execution, without |
115 | // locking, are marked "volatile" | 111 | // locking, are marked "volatile" |
116 | // | 112 | // |
@@ -695,10 +691,11 @@ LUAG_FUNC( linda_deep ) { | |||
695 | LUAG_FUNC( linda_tostring) | 691 | LUAG_FUNC( linda_tostring) |
696 | { | 692 | { |
697 | char text[32]; | 693 | char text[32]; |
698 | struct s_Linda *linda = lua_toLinda( L, 1); | 694 | int len; |
695 | struct s_Linda* linda = lua_toLinda( L, 1); | ||
699 | luaL_argcheck( L, linda, 1, "expected a linda object!"); | 696 | luaL_argcheck( L, linda, 1, "expected a linda object!"); |
700 | sprintf( text, "linda: %p", linda); | 697 | len = sprintf( text, "linda: %p", linda); |
701 | lua_pushstring( L, text); | 698 | lua_pushlstring( L, text, len); |
702 | return 1; | 699 | return 1; |
703 | } | 700 | } |
704 | 701 | ||
@@ -720,15 +717,15 @@ LUAG_FUNC( linda_concat) | |||
720 | if ( linda1) | 717 | if ( linda1) |
721 | { | 718 | { |
722 | char text[32]; | 719 | char text[32]; |
723 | sprintf( text, "linda: %p", linda1); | 720 | int len = sprintf( text, "linda: %p", linda1); |
724 | lua_pushstring( L, text); | 721 | lua_pushlstring( L, text, len); |
725 | lua_replace( L, 1); | 722 | lua_replace( L, 1); |
726 | } | 723 | } |
727 | if ( linda2) | 724 | if ( linda2) |
728 | { | 725 | { |
729 | char text[32]; | 726 | char text[32]; |
730 | sprintf( text, "linda: %p", linda2); | 727 | int len = sprintf( text, "linda: %p", linda2); |
731 | lua_pushstring( L, text); | 728 | lua_pushlstring( L, text, len); |
732 | lua_replace( L, 2); | 729 | lua_replace( L, 2); |
733 | } | 730 | } |
734 | // concat the result | 731 | // concat the result |
@@ -1281,58 +1278,118 @@ LUAG_FUNC( _single ) { | |||
1281 | */ | 1278 | */ |
1282 | #ifdef ERROR_FULL_STACK | 1279 | #ifdef ERROR_FULL_STACK |
1283 | 1280 | ||
1284 | static int lane_error( lua_State *L ) { | 1281 | # define STACK_TRACE_KEY ((void*)lane_error) // used as registry key |
1285 | lua_Debug ar; | 1282 | # define EXTENDED_STACK_TRACE_KEY ((void*)LG_set_error_reporting) // used as registry key |
1286 | unsigned lev,n; | 1283 | |
1284 | #ifdef ERROR_FULL_STACK | ||
1285 | LUAG_FUNC( set_error_reporting) | ||
1286 | { | ||
1287 | bool_t equal; | ||
1288 | luaL_checktype( L, 1, LUA_TSTRING); | ||
1289 | lua_pushliteral( L, "extended"); | ||
1290 | equal = lua_rawequal( L, -1, 1); | ||
1291 | lua_pop( L, 1); | ||
1292 | if( equal) | ||
1293 | { | ||
1294 | goto done; | ||
1295 | } | ||
1296 | lua_pushliteral( L, "basic"); | ||
1297 | equal = !lua_rawequal( L, -1, 1); | ||
1298 | lua_pop( L, 1); | ||
1299 | if( equal) | ||
1300 | { | ||
1301 | return luaL_error( L, "unsupported error reporting model"); | ||
1302 | } | ||
1303 | done: | ||
1304 | lua_pushlightuserdata( L, EXTENDED_STACK_TRACE_KEY); | ||
1305 | lua_pushboolean( L, equal); | ||
1306 | lua_rawset( L, LUA_REGISTRYINDEX); | ||
1307 | return 0; | ||
1308 | } | ||
1309 | #endif // ERROR_FULL_STACK | ||
1310 | |||
1311 | static int lane_error( lua_State* L) | ||
1312 | { | ||
1313 | lua_Debug ar; | ||
1314 | unsigned lev, n; | ||
1315 | bool_t extended; | ||
1287 | 1316 | ||
1288 | // [1]: error message (any type) | 1317 | // [1]: error message (any type) |
1289 | 1318 | ||
1290 | assert( lua_gettop(L)==1 ); | 1319 | assert( lua_gettop( L) == 1); |
1291 | 1320 | ||
1292 | // Don't do stack survey for cancelled lanes. | 1321 | // Don't do stack survey for cancelled lanes. |
1293 | // | 1322 | // |
1294 | #if 1 | 1323 | #if 1 |
1295 | if (lua_touserdata(L,1) == CANCEL_ERROR) | 1324 | if( lua_touserdata( L, 1) == CANCEL_ERROR) |
1296 | return 1; // just pass on | 1325 | return 1; // just pass on |
1297 | #endif | 1326 | #endif |
1298 | 1327 | ||
1299 | // Place stack trace at 'registry[lane_error]' for the 'luc_pcall()' | 1328 | lua_pushlightuserdata( L, EXTENDED_STACK_TRACE_KEY); |
1300 | // caller to fetch. This bypasses the Lua 5.1 limitation of only one | 1329 | lua_gettable( L, LUA_REGISTRYINDEX); |
1301 | // return value from error handler to 'lua_pcall()' caller. | 1330 | extended = lua_toboolean( L, -1); |
1331 | lua_pop( L, 1); | ||
1302 | 1332 | ||
1303 | // It's adequate to push stack trace as a table. This gives the receiver | 1333 | // Place stack trace at 'registry[lane_error]' for the 'lua_pcall()' |
1304 | // of the stack best means to format it to their liking. Also, it allows | 1334 | // caller to fetch. This bypasses the Lua 5.1 limitation of only one |
1305 | // us to add more stack info later, if needed. | 1335 | // return value from error handler to 'lua_pcall()' caller. |
1306 | // | ||
1307 | // table of { "sourcefile.lua:<line>", ... } | ||
1308 | // | ||
1309 | STACK_GROW(L,3); | ||
1310 | lua_newtable(L); | ||
1311 | 1336 | ||
1312 | // Best to start from level 1, but in some cases it might be a C function | 1337 | // It's adequate to push stack trace as a table. This gives the receiver |
1313 | // and we don't get '.currentline' for that. It's okay - just keep level | 1338 | // of the stack best means to format it to their liking. Also, it allows |
1314 | // and table index growing separate. --AKa 22-Jan-2009 | 1339 | // us to add more stack info later, if needed. |
1315 | // | 1340 | // |
1316 | lev= 0; | 1341 | // table of { "sourcefile.lua:<line>", ... } |
1317 | n=1; | 1342 | // |
1318 | while( lua_getstack(L, ++lev, &ar ) ) { | 1343 | STACK_GROW( L, 4); |
1319 | lua_getinfo(L, "Sl", &ar); | 1344 | lua_newtable( L); |
1320 | if (ar.currentline > 0) { | 1345 | |
1321 | lua_pushinteger( L, n++ ); | 1346 | // Best to start from level 1, but in some cases it might be a C function |
1322 | lua_pushfstring( L, "%s:%d", ar.short_src, ar.currentline ); | 1347 | // and we don't get '.currentline' for that. It's okay - just keep level |
1323 | lua_settable( L, -3 ); | 1348 | // and table index growing separate. --AKa 22-Jan-2009 |
1324 | } | 1349 | // |
1325 | } | 1350 | lev = 0; |
1351 | n = 1; | ||
1352 | while( lua_getstack( L, ++ lev, &ar)) | ||
1353 | { | ||
1354 | lua_getinfo( L, extended ? "Sln" : "Sl", &ar); | ||
1355 | if( extended) | ||
1356 | { | ||
1357 | lua_newtable( L); | ||
1358 | |||
1359 | lua_pushstring( L, ar.source); | ||
1360 | lua_setfield( L, -2, "source"); | ||
1326 | 1361 | ||
1327 | lua_pushlightuserdata( L, STACK_TRACE_KEY ); | 1362 | lua_pushinteger( L, ar.currentline); |
1328 | lua_insert(L,-2); | 1363 | lua_setfield( L, -2, "currentline"); |
1329 | lua_settable( L, LUA_REGISTRYINDEX ); | ||
1330 | 1364 | ||
1331 | assert( lua_gettop(L)== 1 ); | 1365 | lua_pushstring( L, ar.name); |
1366 | lua_setfield( L, -2, "name"); | ||
1332 | 1367 | ||
1333 | return 1; // the untouched error value | 1368 | lua_pushstring( L, ar.namewhat); |
1369 | lua_setfield( L, -2, "namewhat"); | ||
1370 | |||
1371 | lua_pushstring( L, ar.what); | ||
1372 | lua_setfield( L, -2, "what"); | ||
1373 | |||
1374 | lua_rawseti(L, -2, n ++); | ||
1375 | } | ||
1376 | else if (ar.currentline > 0) | ||
1377 | { | ||
1378 | lua_pushinteger( L, n++ ); | ||
1379 | lua_pushfstring( L, "%s:%d", ar.short_src, ar.currentline ); | ||
1380 | lua_settable( L, -3 ); | ||
1381 | } | ||
1382 | } | ||
1383 | |||
1384 | lua_pushlightuserdata( L, STACK_TRACE_KEY); | ||
1385 | lua_insert( L ,-2); | ||
1386 | lua_settable( L, LUA_REGISTRYINDEX); | ||
1387 | |||
1388 | assert( lua_gettop( L) == 1); | ||
1389 | |||
1390 | return 1; // the untouched error value | ||
1334 | } | 1391 | } |
1335 | #endif | 1392 | #endif // ERROR_FULL_STACK |
1336 | 1393 | ||
1337 | #if defined PLATFORM_WIN32 && !defined __GNUC__ | 1394 | #if defined PLATFORM_WIN32 && !defined __GNUC__ |
1338 | //see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx | 1395 | //see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx |
@@ -1408,6 +1465,11 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs) | |||
1408 | lua_setglobal( L, "cancel_test" ); | 1465 | lua_setglobal( L, "cancel_test" ); |
1409 | 1466 | ||
1410 | #ifdef ERROR_FULL_STACK | 1467 | #ifdef ERROR_FULL_STACK |
1468 | // Tie "set_error_reporting()" to the state | ||
1469 | // | ||
1470 | lua_pushcfunction( L, LG_set_error_reporting); | ||
1471 | lua_setglobal( L, "set_error_reporting"); | ||
1472 | |||
1411 | STACK_GROW( L, 1 ); | 1473 | STACK_GROW( L, 1 ); |
1412 | lua_pushcfunction( L, lane_error ); | 1474 | lua_pushcfunction( L, lane_error ); |
1413 | lua_insert( L, 1 ); | 1475 | lua_insert( L, 1 ); |
@@ -1885,7 +1947,7 @@ static bool_t thread_cancel( struct s_lane *s, double secs, bool_t force) | |||
1885 | 1947 | ||
1886 | LUAG_FUNC( thread_cancel) | 1948 | LUAG_FUNC( thread_cancel) |
1887 | { | 1949 | { |
1888 | if( lua_gettop( L) != 1 || lua_type( L, 1) != LUA_TUSERDATA) | 1950 | if( lua_gettop( L) < 1 || lua_type( L, 1) != LUA_TUSERDATA) |
1889 | { | 1951 | { |
1890 | return luaL_error( L, "invalid argument #1, did you use ':' as you should?"); | 1952 | return luaL_error( L, "invalid argument #1, did you use ':' as you should?"); |
1891 | } | 1953 | } |