diff --git a/src/lfunc.c b/src/lfunc.c index e2f06b4..8fd9b52 100644 --- a/src/lfunc.c +++ b/src/lfunc.c @@ -132,8 +132,12 @@ static void unlinkupval (UpVal *uv) { void luaF_freeupval(lua_State *L, UpVal *uv) { - if (uv->v != &uv->u.value) /* is it open? */ + if (uv->v != &uv->u.value) { /* is it open? */ + /* Block collector to prevent race with global trace traversing openupval */ + luaC_blockcollector(L); unlinkupval(uv); /* remove from open list */ + luaC_unblockcollector(L); + } luaM_free(L, LUA_MEM_UPVAL, uv); /* free upvalue */ } @@ -144,6 +148,8 @@ void luaF_close (lua_State *L, StkId level) { #if DEBUG_UPVAL printf("close upval >= level %p\n", level); #endif + /* Block collector to prevent race with global trace traversing openupval */ + luaC_blockcollector(L); while (L->openupval.u.l.next != &L->openupval && (uv = L->openupval.u.l.next)->v >= level) { lua_assert(uv->v != &uv->u.value); @@ -156,6 +162,7 @@ void luaF_close (lua_State *L, StkId level) { // setobj(L, &uv->u.value, uv->v); // luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ } + luaC_unblockcollector(L); #if DEBUG_UPVAL dumpopenupvals(L); #endif diff --git a/src/lgc.c b/src/lgc.c index 116a058..4015797 100644 --- a/src/lgc.c +++ b/src/lgc.c @@ -337,6 +337,7 @@ static INLINE int try_block_mutators(lua_State *L) { uint32_t pending; thr_State *pt; + int *recursion = get_recursion(); /* For the non-signal thread stoppage, take a write lock. Important that * we do this before setting intend to stop, as we acquire the write @@ -352,6 +353,8 @@ static INLINE int try_block_mutators(lua_State *L) pthread_rwlock_wrlock(&trace_rwlock); } + (*recursion)++; + /* advertise our intent to stop everyone; this prevents any mutators * from returning from their respective barriers */ ck_pr_store_32(&G(L)->intend_to_stop, 1); @@ -401,6 +404,10 @@ static INLINE int try_block_mutators(lua_State *L) static INLINE void unblock_mutators(lua_State *L) { + int *recursion = get_recursion(); + + (*recursion)--; + ck_pr_store_32(&G(L)->intend_to_stop, 0); ck_pr_fence_memory();