Skip to content

WIP: POE socket support and pipe EOF detection#449

Merged
fglock merged 8 commits into
masterfrom
feature/poe-sockets-and-verification
Apr 7, 2026
Merged

WIP: POE socket support and pipe EOF detection#449
fglock merged 8 commits into
masterfrom
feature/poe-sockets-and-verification

Conversation

@fglock
Copy link
Copy Markdown
Owner

@fglock fglock commented Apr 7, 2026

Summary

This PR adds socket/IO infrastructure needed for the POE event framework test suite:

  • UDP socket support: socket(), bind(), send(), recv() for SOCK_DGRAM; pack_sockaddr_un(); POSIX S_IS* functions
  • Fix select() for DatagramChannel: UDP socket I/O now works with 4-arg select()
  • Fix non-blocking connect and sysread: NIO socket channels handle EINPROGRESS/EAGAIN correctly
  • Fix socket fileno, sysseek, socketpair: fileno() returns consistent fd; sysseek() on non-seekable handles returns error; socketpair() works; listen() preserves port
  • Fix select() in-place bit-vector modification: select() now modifies its bit-vector arguments in-place per Perl semantics
  • Pipe EOF detection: Writer close is now visible to the reader via shared AtomicBoolean; sysread() returns 0 (EOF) instead of blocking

POE test results

Category Count Details
PASS 25 00_info, all_errors, k_alarms, k_aliases, k_detach, k_run_returns, k_selects, k_sig_child, k_signals_rerun, sbk_signal_init, wheel_accept, wheel_curses, wheel_readline, wheel_run, wheel_run_size, wheel_sf_ipv6, wheel_sf_udp, z_kogman_sig_order, z_leolo_wheel_run, z_merijn_sigchld_system, z_rt39872_sigchld, z_rt39872_sigchld_stop, z_rt53302_fh_watchers, z_rt54319_bazerka_followtail, z_steinert_signal_integrity
TIMEOUT 7 Tests pass all assertions but event loop hangs (needs DESTROY on scope exit)
FAIL 3 connect_errors, k_signals (fork), wheel_sf_unix (Unix sockets)

DESTROY support

DESTROY for blessed objects has been moved to a separate PR (#450) where it can be developed with proper reference counting.

Test plan

  • make passes
  • POE test suite: 25/35 pass (up from ~15)

Generated with Devin

@fglock fglock changed the title WIP: POE socket support, pipe EOF detection, and DESTROY for blessed objects WIP: POE socket support and pipe EOF detection Apr 7, 2026
fglock and others added 8 commits April 7, 2026 09:53
Add comprehensive test inventory (~159 files) and prioritized action plan:
- Priority 1: Verify untested regression/pipe tests (+10-15 free wins)
- Priority 2: Debug comp_tcp.t constructor tests (0/34)
- Priority 3: Fix UDP socket support (DatagramChannel)
- Priority 4: Fix Unix domain socket support (Java 16+)
- Priority 5: Investigate k_signals.t self-signal tests
- Priority 6-7: DESTROY workaround and fileno (deferred)

Include failure root cause analysis, projected pass rates, and
hanging test inventory.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…recv buffer

- SocketIO: Add DatagramChannel support for UDP sockets (bind, sendTo,
  recvFrom, getsockname)
- IOOperator: Create DatagramChannel for SOCK_DGRAM, handle UDP send/recv
  with packed sockaddr addresses
- IOOperator: Fix recv() to use scalarDeref() on buffer argument (prototype
  passes it by reference via \\$)
- Socket.java: Add pack_sockaddr_un/unpack_sockaddr_un for Unix domain
  sockets with platform-specific struct format (macOS vs Linux)
- Socket.pm: Export pack_sockaddr_un, unpack_sockaddr_un, sockaddr_un,
  PF_UNIX, AF_UNIX
- POSIX.pm: Add S_ISCHR, S_ISBLK, S_ISFIFO, S_ISSOCK, S_ISLNK functions

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- SocketIO.getSelectableChannel(): Return datagramChannel when available,
  enabling NIO selector registration for UDP sockets
- IOOperator.selectWithNIO(): Handle write-readiness for DatagramChannel
  (previously only SocketChannel was handled for OP_WRITE)

This fixes POE wheel_sf_udp.t (10/10 tests now pass) where the event
loop could not detect incoming UDP data because DatagramChannel was not
returned from getSelectableChannel().

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- selectWithNIO: Call finishConnect() on SocketChannels when OP_CONNECT
  fires, completing the non-blocking connection handshake that Perl
  select() transparently handles
- SocketIO.sysread: Use channel-based I/O even in blocking mode when
  inputStream is not available (accepted sockets via NIO)
- Fixes NotYetConnectedException in sysread after non-blocking connects
- comp_tcp.t now passes 29/34 tests (was 22/34, remaining are DESTROY)

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- SocketIO.fileno(): Return undef so RuntimeIO assigns small sequential fd
  numbers instead of Java hashCode values (millions). Fixes select() which
  uses fd numbers as bit-vector indices.
- RuntimeIO.fileno(): Add SocketIO to lazy fileno assignment types
- sysseek: Register in OperatorHandler and EmitBinaryOperatorNode so JVM
  backend can compile it (was throwing 'no JVM descriptor' error)
- socketpair(): Rewrite to use NIO SocketChannels (was using old-IO Socket
  which can't be monitored by NIO Selector). Auto-vivify glob handles.
- socket(): Pass protocol family to SocketChannel.open() for proper IPv4/6
- SocketIO.connect(): Auto-bind to target address before non-blocking
  connect so getsockname() returns correct local address immediately
- SocketIO.listen(): Preserve actual bound port when converting from
  SocketChannel to ServerSocketChannel (was rebinding to port 0)
- SocketIO.listen(): Transfer non-blocking mode to new ServerSocketChannel
- SocketIO.getsockname(): Check socketChannel.getLocalAddress() before
  falling back to socket.getLocalSocketAddress()
- SocketIO.write/syswrite: Use channel I/O when outputStream unavailable

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Perl's 4-arg select() must modify its first 3 arguments in-place to
reflect which file descriptors are ready. The implementation was
creating snapshot copies of the bit vectors, so the computed results
were never written back to the caller's variables.

This caused POE's select-based event loop to misread fd readiness,
breaking all select-driven I/O (k_selects went from 7/17 to 17/17).

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Pipe EOF: Add shared AtomicBoolean writerClosed between pipe reader and
writer handles. When the writer is closed, sysread on the reader returns
0 (EOF) instead of blocking forever. Use createPair() factory method.

DESTROY: Call DESTROY on blessed objects when:
- delete $hash{key} removes a blessed reference (RuntimeHash)
- undef $var explicitly discards a blessed reference (RuntimeScalar)
- Scope exit in loop bodies (existing scopeExitCleanup path)

Add destroyCalled flag on RuntimeBase to prevent double-DESTROY.
Exceptions in DESTROY are caught and warned "(in cleanup)".

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
DESTROY for blessed objects will be handled in a dedicated branch
(feature/destroy-blessed-objects) where it can be developed with
proper reference counting before merging.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@fglock fglock force-pushed the feature/poe-sockets-and-verification branch from 092bd1b to f8a1b58 Compare April 7, 2026 07:54
@fglock fglock marked this pull request as ready for review April 7, 2026 08:02
@fglock fglock merged commit 618c85e into master Apr 7, 2026
2 checks passed
@fglock fglock deleted the feature/poe-sockets-and-verification branch April 7, 2026 08:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant