If free must return an error because of pointer corruption, the only best solution is to let the lua engine generate a panic and abort the whole process as it is corrupted for all threads; in that case calling luaD_throw in your free tests is the only thing you can do, it will panic and the lua process will be terminated... Then you dont need to return anything else than NULL in a free operation.
The code in lmem.c then never needs to check the L->status...
Except if the memory pool used by your allocator is isolated from the other pool used by other standard allocators in Lua (for example your alloc/free algorithm allocates and check pointers only valid in this pool, inwhich case instead of panicing, you can just invalidate the whole pool and recreate a new one (and all other threads still having pointers in the old pool may just continue to use them as as, but won't get any new pointer from this old pool but from a new clean pool and their attempt to free objects will just be ignored. The old pool will persist as long as there are pointers into it, then Lua will free the old pool itself in one operation during garbage collection.
But if you've detected pointer corruption inside your pool, all threads using objects allocated in that pool are using corrupted objects: do you really want these threads to continue running and using the corrupted objects without being stopped? I see no clear way to recover rather than killing all these threads abruptly.