#code seemingly cut off during execution

63 messages · Page 1 of 1 (latest)

final cipher
#

i really really dont know how to describe this other than the fact that the rest of my function literally doesnt run.
i am working with a c lua binding library (here) and i made a function to set a field in a table. this table is stored in the lua registry, and has to be retrieved with the Push function below to put it onto the lua stack. problem: nothing after that code runs, and the function that SetField is being called in returns immediately and i have no idea how to debug or fix this issue.

here is relevant code (this is work in progress so i dont even know if the rest of it works properly since i cant run it, but it compiles)
* t.mlr.state would be the State type of golua

type Table struct{
    refIdx int
    mlr *Runtime
    nativeFields map[Value]Value
}

func NewTable() *Table {
    return &Table{
        refIdx: -1,
        nativeFields: make(map[Value]Value),
    }
}

func (t *Table) SetRuntime(mlr *Runtime) {
    t.mlr = mlr

    if t.refIdx == -1 {
        mlr.state.NewTable()
        t.refIdx = mlr.state.Ref(lua.LUA_REGISTRYINDEX)
        mlr.state.Pop(1)
    }
}

func (t *Table) Get(val Value) Value {
    return NilValue
}

func (t *Table) Push() {
    t.mlr.state.RawGeti(lua.LUA_REGISTRYINDEX, t.refIdx)
}

func (t *Table) SetField(key string, value Value) {
    fmt.Printf("key: %s, value: %s\n", key, value.TypeName())
    t.Push()
    defer t.mlr.state.Pop(1)

    t.mlr.pushToState(value)
    t.mlr.state.SetField(-1, key)
    t.mlr.state.Pop(1)
    println("what")
}
// another file
func hilbishLoader(mlr *moonlight.Runtime) moonlight.Value {
    println("hilbish loader called")

        // [... code ommitted ...]

    host, _ := os.Hostname()
    username := curuser.Username

    if runtime.GOOS == "windows" {
        username = strings.Split(username, "\\")[1] // for some reason Username includes the hostname on windows
    }

    println("setting ver field")
    hshMod.SetField("ver", moonlight.StringValue(getVersion()))
    println("setting goversion field")
    hshMod.SetField("goVersion", moonlight.StringValue(runtime.Version()))
    hshMod.SetField("user", moonlight.StringValue(username))
    hshMod.SetField("host", moonlight.StringValue(host))
    hshMod.SetField("home", moonlight.StringValue(curuser.HomeDir))
    hshMod.SetField("dataDir", moonlight.StringValue(dataDir))
    hshMod.SetField("interactive", moonlight.BoolValue(interactive))
    hshMod.SetField("login", moonlight.BoolValue(login))
    hshMod.SetField("exitCode", moonlight.IntValue(0))
    //util.SetField(rtm, mod, "vimMode", rt.NilValue)

    // hilbish.userDir table
    hshuser := userDirLoader()
    hshMod.SetField("userDir", moonlight.TableValue(hshuser))

        // [... code ommitted ...]

    return moonlight.TableValue(hshMod)
}
// another file again
func (mlr *Runtime) pushToState(v Value) {
    switch v.Type() {
        case NilType: mlr.state.PushNil()
        case StringType: mlr.state.PushString(v.AsString())
        case TableType:
            tbl := v.AsTable()
            tbl.SetRuntime(mlr)
            mlr.state.RawGeti(lua.LUA_REGISTRYINDEX, tbl.refIdx)
        default: mlr.state.PushNil()
    }
}
//go:build midnight
package moonlight

import (
    "github.com/aarzilli/golua/lua"
)

type Loader func(*Runtime) Value

func (mlr *Runtime) LoadLibrary(ldr Loader, name string) {
    cluaLoader := func (L *lua.State) int {
        mlr.pushToState(ldr(mlr))

        return 1
    }

    mlr.state.GetGlobal("package")
    mlr.state.GetField(-1, "preload")
    mlr.state.PushGoClosure(cluaLoader)
    mlr.state.SetField(-2, name)
    mlr.state.Pop(1)
}

the execution cycle: LoadLibrary is called, package.preload in Lua is set to the go closure. when require 'hilbish' is used, it finally calls the hilbish loader. which is supposed to set all the fields in the table. but it never gets to pushToState (i think? somehow?)

rough yew
#

for my own sake which line of code exactly is being cutoff unexpectedly ?

final cipher
#

errr the t.Push() call in Table.SetField

rough yew
#

Applying the scientific method, trying to prove wrong what you just said
can you try running it with:

func (t *Table) SetField(key string, value Value) {
    fmt.Printf("key: %s, value: %s\n", key, value.TypeName())
    t.Push()
    fmt.Printf("PUSHED key: %s, value: %s\n", key, value.TypeName())
    defer t.mlr.state.Pop(1)

    t.mlr.pushToState(value)
    t.mlr.state.SetField(-1, key)
    t.mlr.state.Pop(1)
    println("what")
}

what is the output ?

#

||this probably give an identical output then will repeat adding print statements to know where it is stopping but inside t.Push||

final cipher
rough yew
#

ok interesting, do you have gopls ?

#

try going inside t.Push (often CTRL + LMB on Push)

final cipher
#

yea but i use lite xl and the lsp support is just "usable enough"

#

i can switch to vsc for a bit

rough yew
#

vsc would work

#

lua based shell, lua based editor
you must really like it ?

final cipher
#

yes :)

final cipher
rough yew
final cipher
#

i think yes

#

yep

rough yew
#

does just doing CTRL + hovering the mouse over Push shows you it's documentation ?

final cipher
#

there's no docs

#

its right above the SetField function 🧍‍♂️

rough yew
#

I mean it should see show something

#

even if it's just it's signature

final cipher
#
func (t *Table) Push() {
    t.mlr.state.RawGeti(lua.LUA_REGISTRYINDEX, t.refIdx)
}
final cipher
#

yes

#

if i have any function related to lua in SetField it just stops

rough yew
#

well I was hopping we could easily see it's code but

func (L *State) RawGeti(index int, n int) {
    C.lua_rawgeti(L.s, C.int(index), C.int(n))
}
final cipher
#

yep bindings

rough yew
#

it looks to be dynamically linked

#

I can't find the impl 😢

final cipher
#

its luajit

#

because if i try to use lua 5.4 proper it seems to.. ignore the build tag

rough yew
#

do you know how to use a debugger ?
Basically what you need to do at this point is look at the code executing inside rawgeti.
You could put a breakpoint right above .Push in your code. then add a breakpoint in rawgeti and continue

#

get an idea where it is failing

final cipher
#

i have no idea on using an actual debugger

rough yew
#

it's really not that hard
in the end you tell it where you want to stop (breakpoint (*Table).Push for example), let the code run continue, then use list to show where it is stopped and step and next to slowly march forward
I find I am better with Printfs but to put Prints in luajit would need to recompile it somehow and given I don't see it embeded in the CGO binding idk what else could be done
you should be able to find tutorials on internet

#

you could recompile it manually and provide the .so file but that sounds like pain

#

otherwise you could try techshamanism
-race -msan -tsan 🤞, verifying your are using lua's binding docs correctly, ...

#

but will be much slower on average

final cipher
#

it apparently.. segfaults?

#

okay

rough yew
#

that looks good

#

progress !

#

can you try s rather than n

#

they do the "same thing" except s goes into function calls while n steps over them

#

wait no nvm I missred the output

#

can you redo the same thing except when you reach SIGSEGV rather than n try bt (backtrace)

final cipher
#

no i know the issue Pepega

rough yew
#

good Sparkles

#

I'm curious what is it ?

final cipher
#

t.mlr is nil

#

lol

rough yew
#

well

#

I'm surprised go doesn't show you the sigsegv as a panic

final cipher
#

right??

rough yew
#

chances luajit and go are fighting over the signal handler

#

signals and CGO don't mix together

#

and SIGSEGV is a signal 😦

final cipher
#

ok problem solved

#

thanks for the hint of using a debugger to debug.. 🙃