LuaJIT FFI type specialization persists after module reload — how to safely invalidate stale ctype caches
0 reputation · 06 Nov 2024, 15:57 UTC
0 reputation · 06 Nov 2024, 15:57 UTC
I am working with LuaJIT's FFI and have run into a design question around type-specialization caching. When a module is reloaded via require (for example after redefining a C struct layout), the recorded type specialization appears to persist, so conversions may still follow the old struct layout. My understanding is that the cache key is derived from the FFI function pointer and type ID, which means a reused pointer after a library reload could silently keep the old specialization active.
The goal is a reliable way to guarantee that, after a struct redefinition or module reload, all subsequent FFI calls use the new type information rather than the cached specialization. I am also unsure whether garbage-collecting the old userdata invalidates anything, since collected objects may still trigger the cached conversion path.
Specific questions:
ffi.flushctype() the only option despite being described as an undocumented workaround?jit.dump output confirm which specialization is active after a reload?35775 reputation · 06 Nov 2024, 23:49 UTC
The only supported way to guarantee that FFI calls use the new type information after a module reload is to call ffi.flushctype() before any further FFI usage.
LuaJIT’s FFI caches type specializations. The cache key is built from the FFI function pointer (or library handle) and the type definition string. When a Lua module is reloaded via require, the underlying C library may be reloaded or the cdef may be re‑executed, but the cache entry is not automatically removed because the key does not incorporate a reload event. Consequently, subsequent FFI conversions can continue to use the stale specialization that matches the old struct layout.
ffi.flushctype() flushes the entire ctype cache and is the documented API for global invalidation; there is no per‑ctype or per‑library flush function in the public LuaJIT API.jit.dump can reveal the generated FFI IR, but interpreting it to determine whether a particular specialization is cached requires familiarity with the dump format and is not a simple staleness flag.local mod = require('mymod') after it has been changed).ffi.flushctype() to clear all cached specializations.ffi.cdef definitions (this is usually done automatically when the module is loaded).After flushing, you can confirm that the new layout is used by checking ffi.sizeof or field offsets against the expected values.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.