MLX support does not seem to work with NIX version
Describe the bug
I was trying to test my so_long project (which uses MinilibX).
If I run funcheck on for example get_next_line it works fine.
If I run it on my so_long project, it seems to hang forever.
To Reproduce Steps to reproduce the behavior:
- Use a
so_longproject as base (or any project that usesMinilibx) - Build it (I use this flake to build my
so_long) - Run
funcheck ./<bin> <args>
Expected behavior It should not hang.
Screenshots
Additional context For exact reproduction steps: as development shell
git clone https://codeberg.org/juke/so_long.git && cd so_long
nix develop "git+https://codeberg.org/juke/42-flakes.nix?dir=so_long" --refresh --no-write-lock-file
# inside development shell
make
funcheck ./so_long maps/map1.ber
or as direct build
git clone https://codeberg.org/juke/so_long.git && cd so_long
nix build "git+https://codeberg.org/juke/42-flakes.nix?dir=so_long" --refresh --no-write-lock-file --impure
funcheck ./result/bin/so_long maps/map1.ber
seems to be any x11 stuff actually, not specifically mlx
i tried this simple gist https://gist.githubusercontent.com/m1nuz/8f8f10a7f8715b62fe79/raw/ac438bd5d757e82c1781d462bfa9be15d657ae31/simple-x11-window.c
and built it with -lX11 and funcheck also hangs on it
heres the last lines of an strace with no fork following
pipe2([3, 6], 0) = 0
openat(AT_FDCWD, "/tmp", O_RDWR|O_EXCL|O_TMPFILE, 0600) = 7
fcntl(7, F_GETFL) = 0x418002 (flags O_RDWR|O_LARGEFILE|O_TMPFILE)
getpid() = 881499
openat(AT_FDCWD, "/dev/shm/funcheck_881499_1733907434_0", O_RDWR|O_CREAT|O_NOFOLLOW|O_CLOEXEC, 0666) = 8
ftruncate(8, 1176) = 0
mmap(NULL, 1176, PROT_READ|PROT_WRITE, MAP_SHARED, 8, 0) = 0x7ffff7dbc000
close(8) = 0
rt_sigaction(SIGRT_1, {sa_handler=0x7ffff7e4dcd0, sa_mask=[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x7ffff7e00620}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
mmap(NULL, 8392704, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7ffff75bb000
mprotect(0x7ffff75bc000, 8388608, PROT_READ|PROT_WRITE) = 0
rt_sigprocmask(SIG_BLOCK, ~[], [], 8) = 0
clone3({flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, child_tid=0x7ffff7dbb990, parent_tid=0x7ffff7dbb990, exit_signal=0, stack=0x7ffff75bb000, stack_size=0x7fff80, tls=0x7ffff7dbb6c0} => {parent_tid=[881502]}, 88) = 881502
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
dup(0) = 8
mmap(NULL, 8392704, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7ffff6dba000
mprotect(0x7ffff6dbb000, 8388608, PROT_READ|PROT_WRITE) = 0
rt_sigprocmask(SIG_BLOCK, ~[], [], 8) = 0
clone3({flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, child_tid=0x7ffff75ba990, parent_tid=0x7ffff75ba990, exit_signal=0, stack=0x7ffff6dba000, stack_size=0x7fff80, tls=0x7ffff75ba6c0} => {parent_tid=[881503]}, 88) = 881503
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7ffff7dbda10) = 881504
close(3) = 0
wait4(881504,
heres the last lines of an strace with fork following
[pid 882162] read(5, <unfinished ...>
[pid 882161] write(1, "main\n??:0:0\n\n", 13 <unfinished ...>
[pid 882162] <... read resumed>"main\n??:0:0\n\n", 4096) = 13
[pid 882161] <... write resumed>) = 13
[pid 882162] write(4, "0x5a0e\n", 7 <unfinished ...>
[pid 882161] read(0, <unfinished ...>
[pid 882162] <... write resumed>) = 7
[pid 882161] <... read resumed>"0x5a0e\n", 4096) = 7
[pid 882162] read(5, <unfinished ...>
[pid 882161] write(1, "??\n??:0:0\n\n", 11 <unfinished ...>
[pid 882162] <... read resumed>"??\n??:0:0\n\n", 4096) = 11
[pid 882161] <... write resumed>) = 11
[pid 882162] write(4, "0x2a27d\n", 8 <unfinished ...>
[pid 882161] read(0, <unfinished ...>
[pid 882162] <... write resumed>) = 8
[pid 882161] <... read resumed>"0x2a27d\n", 4096) = 8
[pid 882162] read(5, <unfinished ...>
[pid 882161] write(1, "??\n??:0:0\n\n", 11 <unfinished ...>
[pid 882162] <... read resumed>"??\n??:0:0\n\n", 4096) = 11
[pid 882161] <... write resumed>) = 11
[pid 882162] write(4, "0x2a338\n", 8 <unfinished ...>
[pid 882161] read(0, <unfinished ...>
[pid 882162] <... write resumed>) = 8
[pid 882161] <... read resumed>"0x2a338\n", 4096) = 8
[pid 882162] read(5, <unfinished ...>
[pid 882161] write(1, "??\n??:0:0\n\n", 11 <unfinished ...>
[pid 882162] <... read resumed>"??\n??:0:0\n\n", 4096) = 11
[pid 882161] <... write resumed>) = 11
[pid 882162] write(4, "0x4028d4\n", 9 <unfinished ...>
[pid 882161] read(0, <unfinished ...>
[pid 882162] <... write resumed>) = 9
[pid 882161] <... read resumed>"0x4028d4\n", 4096) = 9
[pid 882162] read(5, <unfinished ...>
[pid 882161] write(1, "_start\n??:0:0\n\n", 15 <unfinished ...>
[pid 882162] <... read resumed>"_start\n??:0:0\n\n", 4096) = 15
[pid 882161] <... write resumed>) = 15
[pid 882162] mprotect(0x7ffff02fd000, 49152, PROT_READ|PROT_WRITE <unfinished ...>
[pid 882161] read(0, <unfinished ...>
[pid 882162] <... mprotect resumed>) = 0
[pid 882162] futex(0x7ffff7dbc450, FUTEX_WAKE, 1) = 1
[pid 882162] futex(0x7ffff7dbc470, FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, 0, NULL, FUTEX_BITSET_MATCH_ANY <unfinished ...>
[pid 882164] <... futex resumed>) = 0
[pid 882164] futex(0x7ffff7aeb470, FUTEX_WAKE, 1) = 1
[pid 882162] <... futex resumed>) = 0
[pid 882164] futex(0x7ffff7aeb450, FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, 0, NULL, FUTEX_BITSET_MATCH_ANY <unfinished ...>
[pid 882162] futex(0x7ffff7dbc450, FUTEX_WAKE, 1 <unfinished ...>
[pid 882164] <... futex resumed>) = -1 EAGAIN (Resource temporarily unavailable)
[pid 882162] <... futex resumed>) = 0
[pid 882164] futex(0x7ffff7aeb450, FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, 0, NULL, FUTEX_BITSET_MATCH_ANY <unfinished ...>
[pid 882162] futex(0x7ffff7dbc450, FUTEX_WAKE, 1 <unfinished ...>
[pid 882164] <... futex resumed>) = -1 EAGAIN (Resource temporarily unavailable)
[pid 882162] <... futex resumed>) = 0
[pid 882164] recvmsg(6, <unfinished ...>
[pid 882162] futex(0x7ffff7dbc470, FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, 0, NULL, FUTEX_BITSET_MATCH_ANY
i added a bunch of logs until i found where it got stuck and it appears its here specifically https://github.com/froz42/funcheck/blob/main/host/srcs/run/runner.c#L178
Hello, thank for your issue, did you tried the pre-compiled version of funcheck ? I do not think this is related to nix flake
I can't really run prebuilt dynamically linked executables "easily" :( https://nix.dev/guides/faq#how-to-run-non-nix-executables
I have to patch the elf for it to work
But at least the prebuilt version got further and actually "runs" (but very slow and the x11 window is just a black screen)
I'm not really sure its working but compared to the nix build at least it doesn't hang and opens the X window...
ok so after alot of pain i am trying to find the issue...
i added some logs in the mlx hooks...
INFO Running program details:
INFO Program: ./result/bin/so_long
INFO Arguments:
INFO maps/map1.ber
INFO Forking process to run program
INFO Parent process continuing (child pid: 286059)
INFO Initial child process state: R (running)
INFO Child process started (pid: 286059)
INFO X11 Display: :0
INFO XAUTHORITY: not set
INFO Checking X11 socket: /tmp/.X11-unix/X0
INFO X11 socket exists
INFO X11 socket permissions: 755
INFO X11 socket exists and is owned by uid: 1000
INFO Executing program with execvpe
DEBUG: X11 hooks initialized
DEBUG: XSync hook at: 0x7f59096dcbd0
DEBUG: Library constructor called
DEBUG: setup() called
DEBUG: disabled hooks
DEBUG: initialized shared memory
DEBUG: Signals set up
DEBUG: Exit hook set up
DEBUG: setup hooks
DEBUG: setup() complete
DEBUG: XCreateGC hook called with display: 0x1a10b7b0
DEBUG: XCreateGC original function address: 0x7f590954e270
INFO Child process state after 100ms: S (sleeping)
INFO Child process state after 1s: S (sleeping)
i also have debug logs in xsync but for some reason they do not appear...
int EXPORT XSync(Display *a, Bool b)
{
if (getenv("DEBUG"))
fprintf(stderr, "DEBUG: XSync hook called\n");
(void)a;
(void)b;
exit(0);
return 0;
}
ltrace shows that the program does call Xsync....
ltrace -e 'X*' ./result/bin/so_long maps/map1.ber [±master ●(✹)]
so_long->XOpenDisplay(0x4081a8, 0, 0, 0 <unfinished ...>
libX11.so.6->XSetErrorHandler(0, 0, 0, 0xffffff80) = 0x7f8a49160680
libX11.so.6->XSetIOErrorHandler(0, 0, 0, 0) = 0x7f8a49160590
libxcb.so.1->XauGetBestAuthByAddr(256, 10, 0x7ffca9a500c0, 1 <unfinished ...>
libXau.so.6->XauFileName(256, 10, 0x7ffca9a500c0, 1) = 0x21e717c0
<... XauGetBestAuthByAddr resumed> ) = 0
libX11.so.6->XCreateGC(0x21e703c0, 892, 12, 0x7ffca9a503f0) = 0x21e819e0
libX11.so.6->XSynchronize(0x21e703c0, 0, 0, 0) = 0
libX11.so.6->XkbUseExtension(0x21e703c0, 0, 0, 0 <unfinished ...>
libX11.so.6->XInitExtension(0x21e703c0, 0x7f8a491c76cf, 0, 68 <unfinished ...>
libX11.so.6->XQueryExtension(0x21e703c0, 0x7f8a491c76cf, 0x7ffca9a50304, 0x7ffca9a50308) = 1
<... XInitExtension resumed> ) = 0x21e81b78
libX11.so.6->XESetWireToEvent(0x21e703c0, 85, 0x7f8a491b7450, 0) = 0x7f8a4915ff40
<... XkbUseExtension resumed> ) = 1
<... XOpenDisplay resumed> ) = 0x21e703c0
so_long->XInternAtom(0x21e703c0, 0x408207, 0, 0) = 321
so_long->XInternAtom(0x21e703c0, 0x408218, 0, 0) = 313
so_long->XShmQueryVersion(0x21e703c0, 0x7ffca9a5046c, 0x7ffca9a5046c, 0x7ffca9a50468 <unfinished ...>
libXext.so.6->XextFindDisplay(0x7f8a49115820, 0x21e703c0, 0x7ffca9a5046c, 0x7ffca9a50468) = 0
libXext.so.6->XextAddDisplay(0x7f8a49115820, 0x21e703c0, 0x7f8a491100ba, 0x7f8a491154a0 <unfinished ...>
libXext.so.6->XInitExtension(0x21e703c0, 0x7f8a491100ba, 0, 0 <unfinished ...>
libX11.so.6->XQueryExtension(0x21e703c0, 0x7f8a491100ba, 0x7ffca9a50364, 0x7ffca9a50368) = 1
<... XInitExtension resumed> ) = 0x21e81e98
libXext.so.6->XESetWireToEvent(0x21e703c0, 65, 0x7f8a4910a5e0, 0) = 0x7f8a4915ff40
libXext.so.6->XESetEventToWire(0x21e703c0, 65, 0x7f8a4910a530, 0) = 0x7f8a4915ff70
libXext.so.6->XextCreateExtension(0, 130, 0x7f8a491154a0, 71) = 0x21e81a90
libXext.so.6->XextFindDisplay(0x21e81a90, 0x21e703c0, 0, 0) = 0
libXext.so.6->XextAddDisplay(0x21e81a90, 0x21e703c0, 0x7f8a49110200, 0x7f8a49115660 <unfinished ...>
libXext.so.6->XInitExtension(0x21e703c0, 0x7f8a49110200, 0, 0 <unfinished ...>
libX11.so.6->XQueryExtension(0x21e703c0, 0x7f8a49110200, 0x7ffca9a502b4, 0x7ffca9a502b8) = 1
<... XInitExtension resumed> ) = 0x21e81f98
libXext.so.6->XESetCloseDisplay(0x21e703c0, 2, 0x7f8a4910f060, 0) = 0
<... XextAddDisplay resumed> ) = 0x21e81e60
libXext.so.6->XESetWireToEvent(0x21e703c0, 35, 0x7f8a4910eff0, 0) = 0x7f8a4915ff80
libXext.so.6->XESetEventToWire(0x21e703c0, 35, 0x7f8a4910ef70, 0) = 0
libXext.so.6->XESetCloseDisplay(0x21e703c0, 1, 0x7f8a4910a480, 0) = 0
libXext.so.6->XESetErrorString(0x21e703c0, 1, 0x7f8a4910a6a0, 0) = 0
<... XextAddDisplay resumed> ) = 0x21e81e30
<... XShmQueryVersion resumed> ) = 1
so_long->XShmPixmapFormat(0x21e703c0, 0, 0xffffffff, 0 <unfinished ...>
libXext.so.6->XextFindDisplay(0x7f8a49115820, 0x21e703c0, 0xffffffff, 0) = 0x21e81e30
<... XShmPixmapFormat resumed> ) = 2
so_long->XCreateWindow(0x21e703c0, 892, 0, 0) = 0x1c00001
so_long->XGetWMNormalHints(0x21e703c0, 0x1c00001, 0x7ffca9a50320, 0x7ffca9a50318 <unfinished ...>
libX11.so.6->XGetWMSizeHints(0x21e703c0, 0x1c00001, 0x7ffca9a50320, 0x7ffca9a50318 <unfinished ...>
libX11.so.6->XGetWindowProperty(0x21e703c0, 0x1c00001, 40, 0) = 0
<... XGetWMSizeHints resumed> ) = 0
<... XGetWMNormalHints resumed> ) = 0
so_long->XSetWMNormalHints(0x21e703c0, 0x1c00001, 0x7ffca9a50320, 0 <unfinished ...>
libX11.so.6->XSetWMSizeHints(0x21e703c0, 0x1c00001, 0x7ffca9a50320, 40 <unfinished ...>
libX11.so.6->XChangeProperty(0x21e703c0, 0x1c00001, 40, 41) = 1
<... XSetWMSizeHints resumed> ) = 0
<... XSetWMNormalHints resumed> ) = 0
so_long->XStoreName(0x21e703c0, 0x1c00001, 0x4080d0, 0 <unfinished ...>
libX11.so.6->XChangeProperty(0x21e703c0, 0x1c00001, 39, 31) = 1
<... XStoreName resumed> ) = 1
so_long->XSetWMProtocols(0x21e703c0, 0x1c00001, 0x21e703a0, 1 <unfinished ...>
libX11.so.6->XChangeProperty(0x21e703c0, 0x1c00001, 313, 4) = 1
<... XSetWMProtocols resumed> ) = 1
so_long->XCreateGC(0x21e703c0, 0x1c00001, 7, 0x7ffca9a50410) = 0x21e82ba0
so_long->XMapRaised(0x21e703c0, 0x1c00001, 0x21e82838, 0) = 1
so_long->XWindowEvent(0x21e703c0, 0x1c00001, 0x8000, 0x7ffca9a502b0) = 0
so_long->XPutBackEvent(0x21e703c0, 0x7ffca9a502b0, 0, 0) = 0
^[so_long->XShmCreateImage(0x21e703c0, 0x21e7cf60, 24, 2) = 0x21e83250
so_long->XSetErrorHandler(0x4060a0, 0, 0, 0) = 0x7f8a49160680
so_long->XShmAttach(0x21e703c0, 0x21e83228, 0, 0 <unfinished ...>
libXext.so.6->XextFindDisplay(0x7f8a49115820, 0x21e703c0, 0, 0) = 0x21e81e30
<... XShmAttach resumed> ) = 1
so_long->XSync(0x21e703c0, 0, 0, 0) = 1
[...]
but yeah the we seem to never get into the xsync hook...
edit: added a hook for xsyncrhonize which comes right after xcreategc
int (*EXPORT XSynchronize(Display *display, Bool onoff))()
{
printf("DEBUG: XSynchronize called with display=%p, onoff=%d\n", (void*)display, onoff);
disable_alloc_hooks();
typeof(&XSynchronize) original_function = get_original_function();
int (*result)() = original_function(display, onoff);
enable_alloc_hooks();
return result;
}
and i dont see the log when i run funcheck
will update this post as i keep trying stuff...