pgimeno wrote: ↑Thu Feb 24, 2022 12:17 pmI'm beginning to suspect that somehow the Nim library is not being initialized. Maybe ask if someone has experience writing a DLL in Nim that calls library functions.
Well, the crash happens while using the lib, so I don't think there's a problem with loading it. And it doesn't always happen in the same way. I'll explain it better below.
pgimeno wrote: ↑Thu Feb 24, 2022 12:17 pm A bare bones Lua program that loads the DLL and calls the Nim function should be very short and easy, so it's a safe bet. If that doesn't reproduce the problem, you can give up on providing a test case.
The problem is with recreating the crash in a simple project. To clarify, this is for a file-explorer to load images from within my love2d app, which is a font editor for text-based roguelikes (made also with my own two libs (fully in lua), one for a terminal emulator and another for an IM-GUI, and that's why it's big).
What the nim code does so far is just gathering a list of the names of directories and files in the current folder and return it in a table, sorted alphabetically and with the directory names before file names (and a ".." before everything, if the current directory isn't the root). On the lua side I keep the string for the current folder and that list of names, with which I make a list of UI buttons with those names, for navigating the explorer. (The Nim code also changes folders.)
But the crash doesn't happen right away. It always successfully lists files/folders the first time, and I can navigate into other folders. Sometimes when I navigate back out of some folder it crashes. Usually I can reproduce the crash by simply going in and out of my project's
data folder, but still not always. (It does seem like it's when I navigate back, though. I'll have to double-check this, I just noticed it now.)
So it seems that to reproduce this I'd have to sort of replicate the basic behavior of my file explorer somehow on the lua side, in order to go back and forth until it crashes. I can't think of an easy way, though.
pgimeno wrote: ↑Thu Feb 24, 2022 12:17 pm Can you post the backtrace?
Sure. For some reason the backtrace is actually pointing to my code now, which is nice. But it's not always the same line. I'll also post the Nim code below, cleaned up (it uses
nim lua bindings).
Code: Select all
Thread 1 received signal SIGSEGV, Segmentation fault.
0x000000006788b45d in rawAlloc__system_4643 (a=a@entry=0x678ad6c8 <gch.system_5301+104>, requestedSize=requestedSize@entry=41)
at C:/Users/Skaruts/.choosenim/toolchains/nim-1.6.4/lib/system/alloc.nim:788
788 c.freeList = c.freeList.next
(gdb) bt
#0 0x000000006788b45d in rawAlloc__system_4643 (a=a@entry=0x678ad6c8 <gch.system_5301+104>, requestedSize=requestedSize@entry=41)
at C:/Users/Skaruts/.choosenim/toolchains/nim-1.6.4/lib/system/alloc.nim:788
#1 0x0000000067892dde in newObjRC1 (typ=typ@entry=0x678a5000 <strDesc__system_2412>, size=size@entry=25)
at C:/Users/Skaruts/.choosenim/toolchains/nim-1.6.4/lib/system/gc.nim:508
#2 0x0000000067892fbc in copyStringRC1 (src=src@entry=0x2b1d740)
at C:/Users/Skaruts/.choosenim/toolchains/nim-1.6.4/lib/system/sysstr.nim:134
#3 0x00000000678a1e1c in list_dir__skfs_21 (L=0x0)
at I:/Programming/Lua/LOVE/roguelikes/_sillylib-lua/projects/font_editor/src/skfs.nim:72
#4 0x000007fee3f027a3 in ?? () from d:\apps\love\lua51.dll
#5 0x000000013f791910 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
In this backtrace it points to line 72 in my code (skfs.nim). But sometimes it's line 60. Both lines are in the first
for loop (I annotated both in comments -- in the original code they're further apart because of debug prints and stuff).
The crash always happens after the code has successfully stored some file/folder names, somewhere half-way through the for loop. So it doesn't really seem like the problem is related to an invalid path or filename, but I could be wrong. It also doesn't seem related to any particular file type. It has happened with different ones.
Code: Select all
# skfs.nim
from os import nil
from algorithm as algo import nil
import luaw # a few simple abstractions I made (lua's c-api gets imported with it)
proc change_dir(L:PState):cint {.cdecl.} =
let cur_dir:string = L.checkstring(1) # current directory
let rel_dir:string = L.checkstring(2) # target directory (relative to current, not full path, should have no slashes)
var new_dir:string
if rel_dir == os.ParDir:
new_dir = os.parent_dir(cur_dir)
else:
new_dir = os.join_path(cur_dir, rel_dir)
L.pushstring(new_dir) # return new full path string (the lua code uses this string to call 'list_dir')
return 1
proc string_sort(a, b: string):int = # used in 'list_dir' below
if a < b: -1 else: 1
proc list_dir(L:PState):cint {.cdecl.} =
let curr_dir = L.checkstring(1)
L.newtable() # stack : [list]
if not os.dir_exists(curr_dir): return 1
os.set_current_dir(curr_dir) # this seems necessary, couldn't list files without it
var dirs:seq[string]
var files:seq[string]
if not os.is_root_dir(curr_dir): # if this isn't the root, add a ".." item to the list
dirs.add(os.ParDir)
for k, v in os.walk_dir(curr_dir):
var name = os.extract_filename(v) # <-- line 60
if k == os.PathComponent.pcDir:
dirs.add(name)
elif k == os.PathComponent.pcFile:
files.add(name) # <-- line 72
# if len(dirs) > 0: algo.sort(dirs, string_sort) # <-- line 85 (see below)
# if len(files) > 0: algo.sort(files, string_sort)
# 'setfield' are a few helper procs that I made to help populate tables
for i in 0 ..< len(dirs):
# stack : [list]
L.pushnumber(i+1) # stack : [list, i]
L.newtable() # stack : [list, i, t]
L.setfield("type", "dir")
L.setfield("name", dirs[i])
L.settable(-3) # stack : [list]
for i in 0 ..< len(files):
# stack : [list]
L.pushnumber(len(dirs)+i+1) # stack : [list, i]
L.newtable() # stack : [list, i, t]
L.setfield("type", "file")
L.setfield("name", files[i])
L.settable(-3) # stack : [list]
return 1
proc luaopen_skfs(L:PState):cint {.cdecl, exportc, dynlib.} =
var fns = [
reg_func("list_dir", list_dir),
reg_func("change_dir", change_dir),
reg_func() # last empty (must be here)
]
L.register("skfs", addr(fns[0]))
Also, the lines where the names are sorted are commented out for now (right after the first for loop), because if I leave them in, then the crash seems to tend to happen there, instead of in the for loop.
With the sorting lines in, the backtrace is this:
Code: Select all
Thread 1 received signal SIGSEGV, Segmentation fault.
0x00000000678a17f2 in cmpStrings (b=0x10, a=0x10) at C:/Users/Skaruts/.choosenim/toolchains/nim-1.6.4/lib/system/strmantle.nim:16
16 let alen = a.len
(gdb) bt
#0 0x00000000678a17f2 in cmpStrings (b=0x10, a=0x10) at C:/Users/Skaruts/.choosenim/toolchains/nim-1.6.4/lib/system/strmantle.nim:16
#1 string_sort__skfs_10 (a=0x10, b=0x10) at I:/Programming/Lua/LOVE/roguelikes/_sillylib-lua/projects/font_editor/src/skfs.nim:17
#2 0x00000000678971b8 in mergeAlt__skfs_95 (a=a@entry=0x7431060, aLen_0=aLen_0@entry=18, b=b@entry=0x742fa00, bLen_0=9, lo=lo@entry=14,
m=m@entry=14, hi=hi@entry=15, cmp=..., order=order@entry=1 '\001')
at C:/Users/Skaruts/.choosenim/toolchains/nim-1.6.4/lib/pure/algorithm.nim:331
#3 0x00000000678979f4 in sort__skfs_78 (a=0x7431060, a@entry=0x10, aLen_0=18, cmp=..., order=order@entry=1 '\001')
at C:/Users/Skaruts/.choosenim/toolchains/nim-1.6.4/lib/pure/algorithm.nim:413
#4 0x00000000678a255f in list_dir__skfs_21 (L=0x0)
at I:/Programming/Lua/LOVE/roguelikes/_sillylib-lua/projects/font_editor/src/skfs.nim:85
#5 0x000007fee3a827a3 in ?? () from d:\apps\love\lua51.dll
#6 0x000000013fe51910 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
Line 85 is the first sorting line.
Even more weirdly, though, just now I had it crash with no backtrace (well, exiting, it seems), and "virtualFree failing!" is all it says about it. I have no idea what that is. (This was also using the sorting code.)
Code: Select all
virtualFree failing![Thread 4464.0xfec exited with code 1]
[Thread 4464.0x918 exited with code 1]
[Thread 4464.0x15fc exited with code 1]
[Thread 4464.0x1364 exited with code 1]
[Thread 4464.0x1018 exited with code 1]
[Thread 4464.0xf7c exited with code 1]
[Thread 4464.0x17a4 exited with code 1]
[Thread 4464.0x1458 exited with code 1]
[Thread 4464.0x1034 exited with code 1]
[Thread 4464.0xfe4 exited with code 1]
[Inferior 1 (process 4464) exited with code 01]
(gdb) bt
No stack.