'Why does calling lua_newuserdata result in SIGSEGV Segmentation Fault?
I'm trying to identify why a call to lua_newuserdata result in SIGSEGV. The gdb backtrace is :
Thread 2 "main.o" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff7c1a700 (LWP 41635)]
0x0000555555573bbe in sweepstep.constprop ()
(gdb) backtrace
#0 0x0000555555573bbe in sweepstep.constprop ()
#1 0x000055555557531c in singlestep ()
#2 0x0000555555575d22 in luaC_step ()
#3 0x000055555556fbb7 in lua_newuserdatauv ()
To give some scope, this particular call works on numerous invocations -- it only yields this result when I have an io.popen call inside a lua script that runs a process that takes longer to complete than the lifecycle of the lua thread (coroutine) that spawns it. Any help is greatly appreciated. I wonder if stopping the GC with lua_gc(L, GCSTOP)/lua_gc(L, GCRESTART) around the creation of a new lua thread (coroutine) and it's associative offending lua_newuserdata call might help.
EDIT: (apologies for the long code) The repo SIGFAULTs on lua_pushlstring:
#include <stdlib.h>
#include <unistd.h>
#include "lualib.h"
#include "lauxlib.h"
#define NT 18 //it works with a lower value
struct stream_data {
int fd;
int len;
int idx;
char buf[128];
};
struct stream {
lua_State *L;
lua_State *T;
struct stream_data *strm_d;
int id;
int status;
char buf[128];
};
static lua_State *L;
static int active = 0;
static int fref;
struct stream *new_strm(lua_State *L, int i) {
struct stream *strm;
lua_State *T;
char str[64];
int na;
snprintf(str, 64, "thread id: %i", i);
T = lua_newthread(L);
lua_pushlightuserdata(L, T);
strm = (struct stream *) lua_newuserdata(L, sizeof(struct stream));
lua_rawset(L, LUA_REGISTRYINDEX);
lua_pop(L, 1);
lua_rawgeti(T, LUA_REGISTRYINDEX, fref);
lua_pushstring(T, str);
strm->id = i;
strm->T = T;
strm->L = L;
strm->status = lua_resume(T, L, 1, &na);
return strm;
}
static int register_fn(lua_State *L) {
fref = luaL_ref(L, LUA_REGISTRYINDEX);
return 0;
}
int lua_read(lua_State *L) {
struct stream *strm;
struct stream_data *strm_d;
void *sd;
FILE *f;
lua_pushlightuserdata(L, L);
lua_rawget(L, LUA_REGISTRYINDEX);
strm = (struct stream*) lua_touserdata(L, -1);
lua_pop(L, 1);
sd = (void*) lua_touserdata(L, 1);
f = *(FILE**) luaL_checkudata(L, 1, LUA_FILEHANDLE);
lua_pushlightuserdata(L, (void*) sd);
strm_d = lua_newuserdata(L, sizeof(struct stream_data));
lua_rawset(L, LUA_REGISTRYINDEX);
strm_d->len = lua_tointeger(L, 2);
strm_d->idx = 0;
strm_d->fd = fileno(f);
strm->strm_d = strm_d;
return lua_yield(L, 0);
}
int do_read(struct stream *strm) {
struct stream_data *strm_d = strm->strm_d;
int na, rv;
if ((rv = read(strm_d->fd, &strm_d->buf, strm_d->len - strm_d->idx)) >= 0) {
strm_d->idx += rv;
if (strm_d->idx >= strm_d->len) {
lua_pushlstring(strm->T, strm_d->buf, strm_d->len);
strm->status = lua_resume(strm->T, strm->L, 1, &na);
}
}
return 0;
}
static int luaopen_app(lua_State *L) {
struct luaL_Reg functions[] = {
{ "register_fn", register_fn},
{ "read", lua_read },
{ NULL, NULL }
};
luaL_newlib(L, functions);
return 1;
}
lua_State* app_init() {
L = luaL_newstate();
luaL_openlibs(L);
lua_getglobal(L, "package");
lua_getfield(L, -1, "preload");
lua_pushcfunction(L, luaopen_app);
lua_setfield(L, -2, "app");
lua_pop(L, 2);
luaL_loadfile(L, "script.lua");
lua_pcall(L, 0, 0, 0);
return L;
}
int main() {
L = app_init();
struct stream *strm[NT];
int i;
for (i = 0; i < NT; i++) {
strm[i] = new_strm(L, i);
}
while (1) {
int done = 1;
for (i = 0; i < NT; i++) {
if (strm[i]->status == 1) {
do_read(strm[i]);
done = 0;
} else {
lua_gc(L, LUA_GCCOLLECT, 0);
done = 1;
continue;
}
}
if (done == 1)
break;
}
return 0;
}
script.lua
app = require 'app'
local function foo(txt)
print(txt)
local F = assert(io.popen('sh ./script.sh 2', 'r'))
local g = app.read(F, 5)
print(txt..' read: '..g)
print('done')
end
app.register_fn(foo)
script.sh
#!/bin/sh
echo 1 $1
sleep 14
echo 2 $1
echo 3 $1
echo 4 $1
echo 5 $1
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|