| 22 Dec 2025 |
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 |
Randy Eckenrode | https://github.com/apple-oss-distributions/xnu/blob/f6217f891ac0bb64f3d375211650a4c1ff8ca1ea/libsyscall/wrappers/select-base.c#L169 | 16:58:24 |
Randy Eckenrode | It appears the check may be happening prior to the syscall? | 17:00:49 |
Ihar Hrachyshka | implies we would need our own libSystem or smth? :D | 17:01:09 |
Randy Eckenrode | Darwin doesn’t support alternate libcs. There is no guarantee of syscall compatibility between kernel versions. | 17:01:45 |
Randy Eckenrode | (You can try to do it. Go did. Someone got Musl working. If you encounter problems, you’ll be informed that you shouldn’t be doing that.) | 17:02:35 |
Ihar Hrachyshka | guess we could ship a custom select in glib... with some kind of runtime check during build to avoid broken glib if they ever change the behavior... | 17:04:34 |
Randy Eckenrode | https://github.com/apple-oss-distributions/xnu/blob/f6217f891ac0bb64f3d375211650a4c1ff8ca1ea/bsd/sys/_types/_fd_def.h#L37_L40 | 17:04:36 |
Randy Eckenrode | What happens if you define your own FD_SETSIZE? | 17:04:52 |
Ihar Hrachyshka | I assume that since libSystem is as it was compiled with the 1024 limit, it won't do much. but let me check. | 17:05:51 |
Randy Eckenrode | The checks are inline functions in the header. | 17:06:44 |
Randy Eckenrode | Or setting _DARWIN_UNLIMITED_SELECT with select? | 17:07:08 |
Randy Eckenrode | * Or defining _DARWIN_UNLIMITED_SELECT when using select? | 17:07:19 |
Randy Eckenrode | * Or defining _DARWIN_UNLIMITED_SELECT when using select or pselect? | 17:07:42 |
Ihar Hrachyshka | I copied half of that file, commented out include for select.h, removed the check and now it works
=== 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() unexpectedly succeeded with 0 ready FDs
I don't know if "works" means more than "it returned 0" but...
| 17:11:29 |