libvaxis
libvaxis copied to clipboard
Button example crashes when terminal window is resized
It seems that the events are coming from the same thread where the loop happens and mutexes have undefined behavior when lock is called from the same thread. To reproduce:
- Run zig build example -Dexample=counter
- Resize terminal window, tested in Alacritty and Ghostty
The following stack trace can be capture as long you attach to it in another terminal.
Target 0: (example) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
* frame #0: 0x000000018f129388 libsystem_kernel.dylib`__pthread_kill + 8
frame #1: 0x000000018f16288c libsystem_pthread.dylib`pthread_kill + 296
frame #2: 0x000000018f06bc60 libsystem_c.dylib`abort + 124
frame #3: 0x0000000100e59d00 example`posix.abort at posix.zig:710:29
frame #4: 0x0000000100e55a40 example`debug.defaultPanic(msg=(ptr = "Deadlock detected", len = 17), first_trace_addr=(data = 0, some = '\0')) at debug.zig:704:16
frame #5: 0x0000000100e90fa0 example`Thread.Mutex.DebugImpl.lock at Mutex.zig:72:13
frame #6: 0x0000000100e90f08 example`Thread.Mutex.lock(self=0x000000016efada88) at Mutex.zig:34:19
frame #7: 0x0000000100f10ee4 example`queue.Queue(self=0x000000016efa7a78, item=<unavailable>).push at queue.zig:45:28
frame #8: 0x0000000100f07338 example`Loop.Loop(self=0x000000016efa7a68, event=<unavailable>).postEvent at Loop.zig:89:28
frame #9: 0x0000000100ef8520 example`Loop.Loop(ptr=0x000000016efa7a68).winsizeCallback at Loop.zig:103:31
frame #10: 0x0000000100eef58c example`tty.PosixTty.handleWinch at tty.zig:152:29
frame #11: 0x000000018f19c624 libsystem_platform.dylib`_sigtramp + 56
frame #12: 0x0000000100e91138 example`heap.arena_allocator.ArenaAllocator.alloc(ctx=0x00000001010c0080, n=1, alignment=1, ra=4310651692) at arena_allocator.zig:181:48
frame #13: 0x0000000100e9e7e8 example`mem.Allocator.rawAlloc at Allocator.zig:129:26
frame #14: 0x0000000100e9e7c0 example`mem.Allocator.allocBytesWithAlignment__anon_12438(self=<unavailable>, byte_count=1, return_address=4310651692) at Allocator.zig:272:35
frame #15: 0x0000000100e8c9ec example`mem.Allocator.allocWithSizeAndAlignment__anon_10511(self=<unavailable>, n=1, return_address=4310651692) at Allocator.zig:263:40
frame #16: 0x0000000100f0c598 example`mem.Allocator.allocAdvancedWithRetAddr at Allocator.zig:257:75
frame #17: 0x0000000100f0c57c example`mem.Allocator.alignedAlloc__anon_23988(self=<unavailable>, n=1) at Allocator.zig:245:41
frame #18: 0x0000000100ef532c example`array_list.ArrayListAlignedUnmanaged(self=0x000000016efa72e0, allocator=<unavailable>, new_capacity=1).ensureTotalCapacityPrecise at array_list.zig:1094:62
frame #19: 0x0000000100eefd54 example`array_list.ArrayListAlignedUnmanaged(allocator=<unavailable>, num=1).initCapacity at array_list.zig:651:48
frame #20: 0x0000000100eef92c example`InternalScreen.init(alloc=mem.Allocator @ 0x000000016efaddd0, w=258, h=60) at InternalScreen.zig:62:64
frame #21: 0x0000000100ef88e0 example`Vaxis.resize(self=0x000000016efae148, alloc=mem.Allocator @ 0x000000016efaddd0, tty=<unavailable>, winsize=(rows = 60, cols = 258, x_pixel = 3354, y_pixel = 1800)) at Vaxis.zig:202:47
frame #22: 0x0000000100ef194c example`vxfw.App.run(self=0x000000016efae0e8, widget=(userdata = 0x00000001011a0000, captureHandler = 0x0000000000000000, eventHandler = 0x0000000100ef6dd0, drawFn = 0x0000000100ef70c0), opts=(framerate = '<')) at App.zig:147:38
frame #23: 0x0000000100ef0970 example`counter.main at counter.zig:138:16
frame #24: 0x0000000100ef2f3c example`start.callMain at start.zig:660:37 [inlined]
frame #25: 0x0000000100ef2f30 example`start.callMainWithArgs at start.zig:620:20
frame #26: 0x0000000100ef2eb8 example`start.main(c_argc=1, c_argv=0x000000016efaed20, c_envp=0x000000016efaed30) at start.zig:635:28
frame #27: 0x000000018edc2b98 dyld`start + 6076
(lldb) f 6
Root cause is than winsizeCallback runs in the main thread and calls self.postEvent(.{ .winsize = winsize });. But this thread also locks the queue to pull events.
I don't known if it is possible but... running winsizeCallback on the reader thread would fix it