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 | } |
