[PATCH] Lua: Pass image input stream as plain file descriptor

4 views
Skip to first unread message

Christian Storm

unread,
Aug 17, 2026, 4:13:58 PM (9 days ago) Aug 17
to swup...@googlegroups.com
Simplify the FILE* camouflage to just pass the fdin file descriptor
directly as _private.istream_fd instead of a fake FILE* construct.
Input stream validity is checked with fcntl(F_GETFD), preserving
the previous behavior.

This change fixes LuaJIT's Garbage Collector failing with
ERROR in finalizer: bad argument #1 to '?' (FILE* expected, got userdata)
while having no implications on PUC Lua versions.

Note that renaming from _private.istream to _private.istream_fd
is on purpose to reflect the change and since the _private table
is and was never a public interface, this change doesn't break.

Signed-off-by: Christian Storm <christi...@siemens.com>
---
corelib/lua_interface.c | 39 ++++++++++++---------------------------
include/lua_compat.h | 9 ---------
2 files changed, 12 insertions(+), 36 deletions(-)

diff --git a/corelib/lua_interface.c b/corelib/lua_interface.c
index 63703075..f2f1fb85 100644
--- a/corelib/lua_interface.c
+++ b/corelib/lua_interface.c
@@ -634,15 +634,6 @@ static void update_table(lua_State* L, struct img_type *img)
}
}

-#if LUA_VERSION_NUM > 501
-static int l_istream_fclose(lua_State *L)
-{
- /* closing istream is not allowed, ignore it. */
- lua_pushboolean(L, true);
- return 1;
-}
-#endif
-
static void image2table(lua_State* L, struct img_type *img)
{
if (L && img) {
@@ -670,18 +661,17 @@ static void image2table(lua_State* L, struct img_type *img)
update_table(L, img);

if (is_type(L, LUA_TYPE_HANDLER)) {
- lua_getfield(L, -1, "_private");
- lua_pushstring(L, "istream");
- luaL_Stream *lstream = (luaL_Stream *)lua_newuserdata(L, sizeof(luaL_Stream));
- luaL_getmetatable(L, LUA_FILEHANDLE);
- lua_setmetatable(L, -2);
-#if LUA_VERSION_NUM > 501
- lstream->closef = l_istream_fclose;
-#endif
- lstream->f = fdopen(img->fdin, "r");
- if (lstream->f == NULL) {
- WARN("Cannot fdopen file descriptor %d: %s", img->fdin, strerror(errno));
+ int fdin = img->fdin;
+ if (fdin < 0)
+ errno = EBADF;
+ if (fdin < 0 || fcntl(fdin, F_GETFD) == -1) {
+ WARN("Invalid input file descriptor %d: %s", fdin, strerror(errno));
+ fdin = -1;
}
+
+ lua_getfield(L, -1, "_private");
+ lua_pushstring(L, "istream_fd");
+ lua_pushinteger(L, (lua_Integer)fdin);
lua_settable(L, -3);
lua_pop(L, 1);
}
@@ -720,13 +710,8 @@ static void table2image(lua_State* L, struct img_type *img) {
img->offset = (off_t)luaL_checknumber(L, -1);
if (is_type(L, LUA_TYPE_HANDLER)) {
lua_pop(L, 1);
- lua_getfield(L, -1, "istream");
- luaL_Stream *lstream = ((luaL_Stream *)luaL_checkudata(L, -1, LUA_FILEHANDLE));
- if (lstream->f == NULL) {
- img->fdin = -1;
- } else {
- img->fdin = fileno(lstream->f);
- }
+ lua_getfield(L, -1, "istream_fd");
+ img->fdin = (int)luaL_optinteger(L, -1, -1);
}
lua_pop(L,2);
}
diff --git a/include/lua_compat.h b/include/lua_compat.h
index 10075abe..c434bff9 100644
--- a/include/lua_compat.h
+++ b/include/lua_compat.h
@@ -22,15 +22,6 @@ void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup);
void luaL_requiref(lua_State *L, char const* modname, lua_CFunction openf, int glb);


-/*
- * See https://github.com/keplerproject/lua-compat-5.3/wiki/luaL_Stream
- * on the reason for the absence of luaL_Stream's closef member and
- * compatibility with LuaJIT / Lua 5.1.
- */
-typedef struct luaL_Stream {
- FILE *f;
-} luaL_Stream;
-
typedef struct luaL_Buffer_52 {
luaL_Buffer b; /* make incorrect code crash! */
char *ptr;
--
2.55.0

Reply all
Reply to author
Forward
0 new messages