Skip to content

libkernel: fcntl record locks throw on Windows (ProsperoRadio, ProsperoTV after #3649); fix branch ready #4479

Closed

Description

@screamm

With #3649 applied, ProsperoRadio (PPSA99001) stops on #3840's recorded Windows limit: what(): fcntl: record locks are not implemented on Windows, command=12, fd=3 (F_SETLK, at 33.7 s in download0/prosperoradio.log); with the POLLPRI fix (#4478) applied as well, ProsperoTV (PPSA99003) reaches the same line.

Fix branch ready: screamm:feat/libkernel-record-locks-windows: b7cc2856 on top of #3649's two commits on main 33ae282e (depends on #3649 only for the title evidence; the commit itself touches DescriptorControl.cpp and the fcntl test). I cannot open it as a PR under the intake rule while #4081 is open; anyone eligible is welcome to carry it, keeping the commit as is.

  • F_GETLK, F_SETLK, F_SETLKW and the old F_OGETLK/F_OSETLK/F_OSETLKW forms now work on Windows with FreeBSD 11.4's checks in FreeBSD's order (kern_fcntl kern_descrip.c:607-752, lf_advlockasync kern_lockf.c:433-487, vop_stdadvlock, 8c639945): SEEK_CUR resolved against the current offset (EOVERFLOW past the maximum, a directory using its emulated cursor), EBADF for a read lock on a descriptor without read access or a write lock without write access (F_GETLK checks the type but not access), EINVAL for a bad type, negative start, unknown whence or a negative length reaching below 0, EOVERFLOW for SEEK_END past the maximum; F_GETLK writes back F_UNLCK with the adjusted start (24 bytes for the old form). Two cases still throw: a SEEK_END lock on a directory (size unknown) and locks on character devices. Linux is unchanged.
  • No lock table and no LockFileEx backing, deliberately: FreeBSD's lf_blocks lets only locks of different owners conflict, and every lock belongs to the process, so inside the single guest process F_SETLK never returns EAGAIN, F_SETLKW never waits and F_GETLK always reports F_UNLCK; merge/split and release on close are unobservable. Windows byte-range locks are mandatory and would block the guest's own other descriptors (a shared lock blocks writes even through the locking handle), which breaks the POSIX semantics, so other host processes neither see nor are seen by these locks; recorded in the fcntl TechnicalDebt bullet. A table is a contained addition if multi-process support ever arrives.
  • guest_kernel_fcntl: the old Windows "throws" expectation becomes the Linux round trip, plus a new RecordLocksBelongToTheProcess section (round trips, overlap merge and split sequences, two descriptors on one range, a second thread's F_SETLK/F_SETLKW/F_GETLK without conflict, SEEK_CUR/SEEK_END, negative lengths, the 24-byte struct, EINVAL, EBADF on read-only and write-only descriptors, relock after close, EBADF after close); the EOVERFLOW, error-ordering, F_GETLK with F_UNLCK and directory cases are Windows-only, pending Linux CI for the shared part.

Tested on Windows 11 Pro 26220, WinLibs MinGW-w64 GCC 15.2.0 r7, Ninja, Release, BUILD_TESTING=ON, full build including libs: guest_kernel_fcntl, guest_poll, guest_dup, guest_file_vector 3/3; ctest -j8 -E "^agc_driver_|^video_out_flip" 620/620; conventions and git diff --check pass. ProsperoRadio relinked against this build (run 4 runtime, 60 s) opens /download0/radio-browser.sqlite3, starts its service and reaches its HTTP code, then stops at 16.5 s on what(): poll: POLLPRI is not supported by WSAPoll (#4478's fix). Not run on Linux.

Written with Claude Code assistance (implementation by a subagent, reviewed and validated in this session).

Activity

  1. ag6393163475-lab commented on Oct 12, 2026

    @ag6393163475-lab

    Hi! I'd like to work on this issue. Is it still available?
    If so, I'll start on a fix and open a PR once you confirm. Thanks!

  2. milescoviello commented on Oct 12, 2026

    @milescoviello
    Contributor

    Carried in #4480, keeping your commit and authorship; it cherry-picks onto current main without #3649 and builds there. I added the Linux run the issue left to CI: Ubuntu 24.04, GCC 13.3, guest_kernel_fcntl, guest_poll, guest_dup and guest_file_vector pass and all 306 guest_* tests pass; the shared RecordLocksBelongToTheProcess cases also pass with main's DescriptorControl.cpp, so Linux is unchanged. I can't run Windows here, so the Windows results in the PR are yours from this issue. Thanks for the branch.

    @ag6393163475-lab, since a finished fix branch was already here, I carried it as the issue asks rather than starting a new one.

    AI-assisted: yes

  3. screamm commented on Oct 12, 2026

    @screamm
    ContributorAuthor

    Combined run on Windows (main 33ae282e + #3649's two commits + the POLLPRI fix from #4478 + the record-lock fix from #4479, all cherry-picking cleanly; run 4 runtime with that build's libs and relinker, 60 s each): ProsperoRadio (PPSA99001) and ProsperoTV (PPSA99003) get past poll and the record locks and now stop on the graphics side, [videoout] presentation failed: AGC graphics: last provoking vertex with explicit per-vertex flat interpolation is unsupported (open #4030); PSXS5 (PPSA97510) runs the whole minute at PSXS5 | FPS: 59.93 (2867); SwanStation (PPSA98510) runs the whole minute (SwanStationPS5 ready, pad detected, its gamedb download fails with curl 7). No library stop is left in these four that lacks a PR. One observation for later: every HTTPS request from inside the guest fails immediately in these titles (Failed to connect to all.api.radio-browser.info port 443 after 75 ms, curl 7) while the same URLs answer from the host shell; it produces no stop line, and PSXS5 logged it before these fixes too. (#4480 carries this fix; thanks.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions