aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lcorolib.c12
-rw-r--r--ldo.c4
-rw-r--r--manual/manual.of33
-rw-r--r--testes/coroutine.lua8
-rw-r--r--testes/db.lua14
-rw-r--r--testes/locals.lua35
6 files changed, 80 insertions, 26 deletions
diff --git a/lcorolib.c b/lcorolib.c
index f7c9e165..a21880d5 100644
--- a/lcorolib.c
+++ b/lcorolib.c
@@ -25,6 +25,10 @@ static lua_State *getco (lua_State *L) {
25} 25}
26 26
27 27
28/*
29** Resumes a coroutine. Returns the number of results for non-error
30** cases or -1 for errors.
31*/
28static int auxresume (lua_State *L, lua_State *co, int narg) { 32static int auxresume (lua_State *L, lua_State *co, int narg) {
29 int status, nres; 33 int status, nres;
30 if (!lua_checkstack(co, narg)) { 34 if (!lua_checkstack(co, narg)) {
@@ -74,8 +78,14 @@ static int luaB_auxwrap (lua_State *L) {
74 lua_State *co = lua_tothread(L, lua_upvalueindex(1)); 78 lua_State *co = lua_tothread(L, lua_upvalueindex(1));
75 int r = auxresume(L, co, lua_gettop(L)); 79 int r = auxresume(L, co, lua_gettop(L));
76 if (r < 0) { 80 if (r < 0) {
81 int stat = lua_status(co);
82 if (stat != LUA_OK && stat != LUA_YIELD) {
83 stat = lua_resetthread(co); /* close variables in case of errors */
84 if (stat != LUA_OK) /* error closing variables? */
85 lua_xmove(co, L, 1); /* get new error object */
86 }
77 if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */ 87 if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */
78 luaL_where(L, 1); /* add extra info */ 88 luaL_where(L, 1); /* add extra info, if available */
79 lua_insert(L, -2); 89 lua_insert(L, -2);
80 lua_concat(L, 2); 90 lua_concat(L, 2);
81 } 91 }
diff --git a/ldo.c b/ldo.c
index 2a98c397..d474c0a0 100644
--- a/ldo.c
+++ b/ldo.c
@@ -686,10 +686,8 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
686 if (likely(!errorstatus(status))) 686 if (likely(!errorstatus(status)))
687 lua_assert(status == L->status); /* normal end or yield */ 687 lua_assert(status == L->status); /* normal end or yield */
688 else { /* unrecoverable error */ 688 else { /* unrecoverable error */
689 status = luaF_close(L, L->stack, status); /* close all upvalues */
690 L->status = cast_byte(status); /* mark thread as 'dead' */ 689 L->status = cast_byte(status); /* mark thread as 'dead' */
691 luaD_seterrorobj(L, status, L->stack + 1); /* push error message */ 690 luaD_seterrorobj(L, status, L->top); /* push error message */
692 L->ci = &L->base_ci; /* back to the original C level */
693 L->ci->top = L->top; 691 L->ci->top = L->top;
694 } 692 }
695 *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield 693 *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield
diff --git a/manual/manual.of b/manual/manual.of
index 5f265708..cf44b4f2 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -286,7 +286,7 @@ Lua also offers a system of @emph{warnings} @seeF{warn}.
286Unlike errors, warnings do not interfere 286Unlike errors, warnings do not interfere
287in any way with program execution. 287in any way with program execution.
288They typically only generate a message to the user, 288They typically only generate a message to the user,
289although this behavior can be adapted from C @see{lua_setwarnf}. 289although this behavior can be adapted from C @seeC{lua_setwarnf}.
290 290
291} 291}
292 292
@@ -835,6 +835,9 @@ In case of normal termination,
835plus any values returned by the coroutine main function. 835plus any values returned by the coroutine main function.
836In case of errors, @Lid{coroutine.resume} returns @false 836In case of errors, @Lid{coroutine.resume} returns @false
837plus the error object. 837plus the error object.
838In this case, the coroutine does not unwind its stack,
839so that it is possible to inspect it after the error
840with the debug API.
838 841
839A coroutine yields by calling @Lid{coroutine.yield}. 842A coroutine yields by calling @Lid{coroutine.yield}.
840When a coroutine yields, 843When a coroutine yields,
@@ -858,8 +861,10 @@ go as extra arguments to @Lid{coroutine.resume}.
858@Lid{coroutine.wrap} returns all the values returned by @Lid{coroutine.resume}, 861@Lid{coroutine.wrap} returns all the values returned by @Lid{coroutine.resume},
859except the first one (the boolean error code). 862except the first one (the boolean error code).
860Unlike @Lid{coroutine.resume}, 863Unlike @Lid{coroutine.resume},
861@Lid{coroutine.wrap} does not catch errors; 864the function created by @Lid{coroutine.wrap}
862any error is propagated to the caller. 865propagates any error to the caller.
866In this case,
867the function also kills the coroutine @seeF{coroutine.kill}.
863 868
864As an example of how coroutines work, 869As an example of how coroutines work,
865consider the following code: 870consider the following code:
@@ -1534,8 +1539,15 @@ the other pending closing methods will still be called.
1534If a coroutine yields inside a block and is never resumed again, 1539If a coroutine yields inside a block and is never resumed again,
1535the variables visible at that block will never go out of scope, 1540the variables visible at that block will never go out of scope,
1536and therefore they will not be closed. 1541and therefore they will not be closed.
1537(You should use finalizers to handle this case, 1542Similarly, if a coroutine ends with an error,
1538or else call @Lid{coroutine.kill} to close the variables.) 1543it does not unwind its stack,
1544so it does not close any variable.
1545You should either use finalizers
1546or call @Lid{coroutine.kill} to close the variables in these cases.
1547However, note that if the coroutine was created
1548through @Lid{coroutine.wrap},
1549then its corresponding function will close all variables
1550in case of errors.
1539 1551
1540} 1552}
1541 1553
@@ -6406,11 +6418,12 @@ or if it has stopped with an error.
6406Creates a new coroutine, with body @id{f}; 6418Creates a new coroutine, with body @id{f};
6407@id{f} must be a function. 6419@id{f} must be a function.
6408Returns a function that resumes the coroutine each time it is called. 6420Returns a function that resumes the coroutine each time it is called.
6409Any arguments passed to the function behave as the 6421Any arguments passed to this function behave as the
6410extra arguments to @id{resume}. 6422extra arguments to @id{resume}.
6411Returns the same values returned by @id{resume}, 6423The function returns the same values returned by @id{resume},
6412except the first boolean. 6424except the first boolean.
6413In case of error, propagates the error. 6425In case of error,
6426the function kills the coroutine and propagates the error.
6414 6427
6415} 6428}
6416 6429
@@ -6668,6 +6681,10 @@ the file path where the module was found,
6668as returned by @Lid{package.searchpath}. 6681as returned by @Lid{package.searchpath}.
6669The first searcher always returns the string @St{:preload:}. 6682The first searcher always returns the string @St{:preload:}.
6670 6683
6684Searchers should raise no errors and have no side effects in Lua.
6685(They may have side effects in C,
6686for instance by linking the application with a library.)
6687
6671} 6688}
6672 6689
6673@LibEntry{package.searchpath (name, path [, sep [, rep]])| 6690@LibEntry{package.searchpath (name, path [, sep [, rep]])|
diff --git a/testes/coroutine.lua b/testes/coroutine.lua
index 35ff27fb..9dd501e7 100644
--- a/testes/coroutine.lua
+++ b/testes/coroutine.lua
@@ -346,9 +346,13 @@ do
346 local st, res = coroutine.resume(B) 346 local st, res = coroutine.resume(B)
347 assert(st == true and res == false) 347 assert(st == true and res == false)
348 348
349 A = coroutine.wrap(function() return pcall(A, 1) end) 349 local X = false
350 A = coroutine.wrap(function()
351 local *toclose _ = setmetatable({}, {__close = function () X = true end})
352 return pcall(A, 1)
353 end)
350 st, res = A() 354 st, res = A()
351 assert(not st and string.find(res, "non%-suspended")) 355 assert(not st and string.find(res, "non%-suspended") and X == true)
352end 356end
353 357
354 358
diff --git a/testes/db.lua b/testes/db.lua
index 95275fb4..3d94f776 100644
--- a/testes/db.lua
+++ b/testes/db.lua
@@ -734,18 +734,24 @@ a, b = coroutine.resume(co, 100)
734assert(a and b == 30) 734assert(a and b == 30)
735 735
736 736
737-- check traceback of suspended coroutines 737-- check traceback of suspended (or dead with error) coroutines
738
739function f(i)
740 if i == 0 then error(i)
741 else coroutine.yield(); f(i-1)
742 end
743end
738 744
739function f(i) coroutine.yield(i == 0); f(i - 1) end
740 745
741co = coroutine.create(function (x) f(x) end) 746co = coroutine.create(function (x) f(x) end)
742a, b = coroutine.resume(co, 3) 747a, b = coroutine.resume(co, 3)
743t = {"'coroutine.yield'", "'f'", "in function <"} 748t = {"'coroutine.yield'", "'f'", "in function <"}
744repeat 749while coroutine.status(co) == "suspended" do
745 checktraceback(co, t) 750 checktraceback(co, t)
746 a, b = coroutine.resume(co) 751 a, b = coroutine.resume(co)
747 table.insert(t, 2, "'f'") -- one more recursive call to 'f' 752 table.insert(t, 2, "'f'") -- one more recursive call to 'f'
748until b 753end
754t[1] = "'error'"
749checktraceback(co, t) 755checktraceback(co, t)
750 756
751 757
diff --git a/testes/locals.lua b/testes/locals.lua
index de47ae31..814d1b16 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -417,12 +417,13 @@ if rawget(_G, "T") then
417end 417end
418 418
419 419
420-- to-be-closed variables in coroutines 420print "to-be-closed variables in coroutines"
421
421do 422do
422 -- an error in a coroutine closes variables 423 -- an error in a wrapped coroutine closes variables
423 local x = false 424 local x = false
424 local y = false 425 local y = false
425 local co = coroutine.create(function () 426 local co = coroutine.wrap(function ()
426 local *toclose xv = func2close(function () x = true end) 427 local *toclose xv = func2close(function () x = true end)
427 do 428 do
428 local *toclose yv = func2close(function () y = true end) 429 local *toclose yv = func2close(function () y = true end)
@@ -432,14 +433,31 @@ do
432 error(23) -- error does 433 error(23) -- error does
433 end) 434 end)
434 435
435 local a, b = coroutine.resume(co) 436 local b = co()
436 assert(a and b == 100 and not x and not y) 437 assert(b == 100 and not x and not y)
437 a, b = coroutine.resume(co) 438 b = co()
438 assert(a and b == 200 and not x and y) 439 assert(b == 200 and not x and y)
439 a, b = coroutine.resume(co) 440 local a, b = pcall(co)
440 assert(not a and b == 23 and x and y) 441 assert(not a and b == 23 and x and y)
441end 442end
442 443
444
445do
446 -- error in a wrapped coroutine raising errors when closing a variable
447 local x = false
448 local co = coroutine.wrap(function ()
449 local *toclose xv = func2close(function () error("XXX") end)
450 coroutine.yield(100)
451 error(200)
452 end)
453 assert(co() == 100)
454 local st, msg = pcall(co)
455print(msg)
456 -- should get last error raised
457 assert(not st and string.find(msg, "%w+%.%w+:%d+: XXX"))
458end
459
460
443-- a suspended coroutine should not close its variables when collected 461-- a suspended coroutine should not close its variables when collected
444local co 462local co
445co = coroutine.wrap(function() 463co = coroutine.wrap(function()
@@ -449,6 +467,7 @@ co = coroutine.wrap(function()
449end) 467end)
450co() -- start coroutine 468co() -- start coroutine
451assert(co == nil) -- eventually it will be collected 469assert(co == nil) -- eventually it will be collected
470collectgarbage()
452 471
453 472
454-- to-be-closed variables in generic for loops 473-- to-be-closed variables in generic for loops