| 805 | |
| 806 | |
| 807 | static void GCTM (lua_State *L, int propagateerrors) { |
| 808 | global_State *g = G(L); |
| 809 | const TValue *tm; |
| 810 | TValue v; |
| 811 | setgcovalue(L, &v, udata2finalize(g)); |
| 812 | tm = luaT_gettmbyobj(L, &v, TM_GC); |
| 813 | if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ |
| 814 | int status; |
| 815 | lu_byte oldah = L->allowhook; |
| 816 | int running = g->gcrunning; |
| 817 | L->allowhook = 0; /* stop debug hooks during GC metamethod */ |
| 818 | g->gcrunning = 0; /* avoid GC steps */ |
| 819 | setobj2s(L, L->top, tm); /* push finalizer... */ |
| 820 | setobj2s(L, L->top + 1, &v); /* ... and its argument */ |
| 821 | L->top += 2; /* and (next line) call the finalizer */ |
| 822 | L->ci->callstatus |= CIST_FIN; /* will run a finalizer */ |
| 823 | status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); |
| 824 | L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */ |
| 825 | L->allowhook = oldah; /* restore hooks */ |
| 826 | g->gcrunning = running; /* restore state */ |
| 827 | if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ |
| 828 | if (status == LUA_ERRRUN) { /* is there an error object? */ |
| 829 | const char *msg = (ttisstring(L->top - 1)) |
| 830 | ? svalue(L->top - 1) |
| 831 | : "no message"; |
| 832 | luaO_pushfstring(L, "error in __gc metamethod (%s)", msg); |
| 833 | status = LUA_ERRGCMM; /* error in __gc metamethod */ |
| 834 | } |
| 835 | luaD_throw(L, status); /* re-throw error */ |
| 836 | } |
| 837 | } |
| 838 | } |
| 839 | |
| 840 | |
| 841 | /* |
no test coverage detected