Repository navigation
Conversation
net.c was POSIX sockets only, and line 17 said so: Windows needs Winsock before the desktop app can use the native path. build-helper.mjs already listed ws2_32, ole32 and winmm, so the link flags were staged for this. One typedef per difference rather than two copies of the body: gv_socket, gv_thread, gv_socklen, GV_BAD_SOCKET, gv_close_socket. Winsock's socket is an unsigned handle, so the old "fd < 0" test can never catch a failed one and INVALID_SOCKET is the only correct check. WSAStartup is reference counted, because it has to be stopped as many times as it was started and a host that called it first must not be torn out from under. The receive thread is CreateThread on Windows and still joins before the socket closes, or it blocks in recvfrom on a handle that is gone. SO_RCVTIMEO is a timeval on POSIX and a DWORD of milliseconds on Winsock; passing the wrong one sets a nonsense timeout rather than failing, so it has its own function. build-helper.mjs stops passing -lm on Windows, where the MSVC runtime has no separate libm and it is a hard link error, and defines _CRT_SECURE_NO_WARNINGS rather than printing the CRT's opinion of strtok forty times. _DEFAULT_SOURCE is now POSIX-only. Verified on Windows with clang 23.1.5: the helper builds, and native/tools/test_net.c exercises engine init, net open and net close with no audio device and reports ALL OK. Two things found on the way and not fixed here. gv_engine does not fit Windows' 1MB default stack, where Linux gives 8MB, so anything holding one by value crashes with 0xC00000FD; gv_voice already callocs it, and the test harness says why it does too. And gryt-voice still hangs on Windows after this port, in gv_device_start rather than in the socket layer, which is device.c and its own problem. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
test_net.c already covered engine and net. test_device.c adds the audio device and test_voice.c drives gv_voice_start, levels and stop. All three pass on Windows with clang 23.1.5: engine_init ... ok device_start(period=960) ... ok, mic channels=1 voice_start(period=960) ... ok, route=-1 voice_levels ... ok, 0 senders, mic -inf ALL OK So the library works on Windows after the Winsock port. What still crashes is gryt-voice itself, with 0xC0000409, and the difference is voice_helper.c. Not the reader thread's stack: giving CreateThread 8MB changes nothing, and that attempt is not in this commit. Not the audio period either; 960 and 20 both work through the harnesses. ASan reports nothing before the fast-fail. It wants a debugger rather than another guess. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Chased the remaining Windows crash. The port is better than I claimed and the crash is narrower than I thought. The library works on WindowsThree harnesses, each adding one layer, all passing with clang 23.1.5:
So What still crashes is
|
gryt-voice died on Windows with 0xC0000409 before printing anything. It was not the socket layer, the audio device, the period, the thread stack or the link stack. It was line 164: setvbuf(stdout, NULL, _IOLBF, 0); glibc reads a NULL buffer with size 0 as "pick a size". The MSVC runtime requires a size of at least 2 for _IOLBF, so this left stdout in a state where the first write corrupted the stack and the cookie check fast-failed. Hence no output at all rather than a partial line, and hence a corruption code rather than exhaustion. Unbuffered instead of line buffered, which is also simply correct here: every write is a whole line followed by fflush, so the buffer bought nothing. The three harnesses used _IONBF, where size is ignored, which is exactly why they all passed while the real binary did not. Windows now matches Linux byte for byte: started 1 r -1 -120.0 0 l= b= s= t= Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
net.cwas POSIX sockets only, and line 17 said exactly that: "Windows needs Winsock here before the desktop app can use the native path."build-helper.mjsalready listedws2_32,ole32andwinmm, so the link flags were staged for this and only the code was missing.Shape of it
One typedef per platform difference rather than two copies of the body:
gv_socket,gv_thread,gv_socklen,GV_BAD_SOCKET,gv_close_socket. The bodies ofsend_packet, the receive loop andresolveread the same on both.What to look at
GV_BAD_SOCKETinstead offd < 0. Winsock'sSOCKETis an unsigned handle, so the old test can never catch a failed socket. This is the one change that is a latent bug fix rather than a port.WSAStartupis reference counted. It has to be stopped as many times as it was started, and a host process that called it before us must not be torn out from under. If you would rather@gryt/voicenever touch global Winsock state and leave it to the embedder, say so — that is a reasonable different answer and it changes this function.set_recv_timeouthas its own function becauseSO_RCVTIMEOis atimevalon POSIX and aDWORDof milliseconds on Winsock. Pass the wrong one and you get a nonsense timeout rather than an error, which is the sort of thing that shows up months later as "voice is laggy on Windows".recvfromon a handle that is gone. The 200ms timeout is what bounds that wait, which is why it exists.Verified
Windows, clang 23.1.5: the helper builds (1.0 MB), and
native/tools/test_net.cexercises engine init, net open and net close with no audio device:Linux is unaffected and still builds, checked on Debian 12 with gcc 12.2.
Two things found and deliberately not fixed here
gv_enginedoes not fit Windows' 1 MB default stack. Linux gives 8 MB. Anything holding one by value dies with0xC00000FDbeforemainprints.gv_voicealreadycallocs it, so nothing shipping is affected, but it is a trap for the next person who writes a test, which is how I found it. The harness carries a comment saying so.gryt-voicestill hangs on Windows after this. Not in the socket layer:gv_voice_startgoes engine, then net, thengv_device_start, and the harness above proves the first two complete. So it isdevice.cand miniaudio's WASAPI backend, which is its own problem and wants its own change.Build flags
-lmis gone on Windows, where the MSVC runtime has no separate libm and it is a hard link error rather than a no-op._CRT_SECURE_NO_WARNINGSreplaces forty lines of the CRT's opinion ofstrtok._DEFAULT_SOURCEis now POSIX-only.🤖 Generated with Claude Code