| 22 Dec 2025 |
Ihar Hrachyshka | maybe the original reasoning documented in the comment is no longer applicable, but tap device polling is still an issue. | 15:55:30 |
Randy Eckenrode | Maybe it only works on newer macOS? | 15:57:29 |
hexa | it's a bit surprising that nix-darwin does not have a system.autoUpgrade like option 🤔 | 15:58:04 |
hexa | what I need is to keep the machines in sync with a flake ref | 15:58:43 |
Randy Eckenrode | The test is whether it supports devices. According to POSIX:
The poll() and ppoll() functions shall support regular files, terminal and pseudo-terminal devices, FIFOs, pipes, and sockets. The behavior of poll() and ppoll() on elements of fds that refer to other types of file is unspecified.
| 16:00:23 |
Randy Eckenrode | So it doesn’t appear that it’s required to support devices other than (P)TTYs. | 16:01:03 |
Ihar Hrachyshka | it's a gnu world... | 16:01:17 |
Randy Eckenrode | If Glib does want to support that, they need emulation. | 16:01:33 |
Randy Eckenrode | It might be possible to do it with kqueue. That’s how Apple implements poll in XNU. They probably don’t support devices because it’s not required. | 16:02:58 |
Ihar Hrachyshka | qemu defines fd array as GPollFD poll_fds[1024 * 2]; /* this is probably overkill */ which AFAIU is above the limit on darwin. but then it's probably not something that would be solved by reducing the size of the array since - I assume - qemu has a good reason to listen on so many files (is it because of how nix store is overlayed into these vms?) | 16:04:40 |
Randy Eckenrode | Does it work if the fd limit is increased? | 16:05:31 |
Ihar Hrachyshka | maybe I should (somehow) map fds opened by the process to actual files and see what's in the top | 16:05:43 |
Ihar Hrachyshka | can one increas the limit? thought it's hardcoded in includes and darwin enforces it (which I think is how I get the traceback in Console in the first place) | 16:06:15 |
Ihar Hrachyshka | the traceback with enforcement
Thread 13 Crashed:
0 libsystem_kernel.dylib 0x1903409f4 os_fault_with_payload + 8
1 libsystem_kernel.dylib 0x190348964 __darwin_check_fd_set_overflow + 212
2 libglib-2.0.0.dylib 0x10790fc64 g_poll + 196
3 qemu-system-aarch64 0x104df8158 main_loop_wait + 336
4 qemu-system-aarch64 0x104750064 qemu_main_loop + 96
5 qemu-system-aarch64 0x104d2c06c qemu_default_main + 36
6 qemu-system-aarch64 0x104de5300 qemu_thread_start + 132
7 libsystem_pthread.dylib 0x190374c08 _pthread_start + 136
8 libsystem_pthread.dylib 0x19036fba8 thread_start + 8
| 16:13:33 |
Ihar Hrachyshka | also in the VM (that still runs but is not responsive) sometimes I can see klogs suggesrting hanging tasks like jbd2/vda or journald suggesting writing to disk is blocked. which is why I suspect storage. | 16:18:01 |
Randy Eckenrode | Oh, FD_SET overflow. I was thinking of the limit of number of open fds. | 16:23:34 |
Ihar Hrachyshka | ah you meant ulimit? I set it to unlimited. that's not the issue. it crashes at ~1024 (as per lsof). | 16:24:05 |
Randy Eckenrode | Does it work if you change select to pselect? | 16:28:53 |
Randy Eckenrode | The implementation implies that there’s no limit for pselect. | 16:30:05 |
Ihar Hrachyshka | qemu definitely needs to - also - poll on device files (for tap etc.) so if darwin doesn't implement it for poll(), one can't work around it without some other API. glib uses select but it has FD_SET issue. we are left with implementing it with something else, like kqueue. but...
if I poll /dev/null with kqueue I get
kevent register: Invalid argument
| 16:30:55 |
Randy Eckenrode | Or that there is a set pf Darwin extensions that removes the limit. | 16:31:59 |
Ihar Hrachyshka |
Does it work if you change select to pselect? recompiling glib with select -> pselect in g_poll?
| 16:32:54 |
Ihar Hrachyshka | *
Does it work if you change select to pselect? recompiling glib with select -> pselect in g_poll?
| 16:32:59 |
Ihar Hrachyshka | *
Does it work if you change select to pselect?
recompiling glib with select -> pselect in g_poll?
| 16:33:04 |
Randy Eckenrode | Yeah. | 16:33:38 |
Ihar Hrachyshka | I'll try later today, it's a good lead. (have to step off this for the next few). thanks a lot for engaging. :) | 16:35:11 |
Ihar Hrachyshka | meh. a vibe coded test is not very promising
=== Test 1: pselect() with FDs < FD_SETSIZE ===
pselect() succeeded with 1021 ready FDs
=== Test 2: pselect() with FD >= FD_SETSIZE (DANGEROUS!) ===
This test intentionally demonstrates undefined behavior
Attempting to add FD 1024 to fd_set (FD_SETSIZE=1024)...
WARNING: This will cause undefined behavior!
Before FD_SET: fd_set memory looks normal
fd_set bytes before: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Calling FD_SET(1024, &dangerous_set)...
fd_set bytes after: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Memory corruption may have occurred!
Attempting pselect() with corrupted fd_set...
pselect: Invalid argument
pselect() failed as expected
| 16:45:46 |
Ihar Hrachyshka | Thread 0 Crashed:
0 libsystem_kernel.dylib 0x1956749f4 os_fault_with_payload + 8
1 libsystem_kernel.dylib 0x19567c964 __darwin_check_fd_set_overflow + 212
2 a.out 0x104adcc94 main + 2100
3 dyld 0x1952e9d54 start + 7184
same cause
| 16:48:37 |
Randy Eckenrode | How do we enable these extensions? 🤔 | 16:57:38 |
Ihar Hrachyshka | which extensions? link? | 16:57:48 |