Skip to content

Harden TCP/UDP socket loops and use RTHS-friendly network defaults#6

Open
joecga4 wants to merge 1 commit into
aschellenberg74:masterfrom
joecga4:fix/tcp-udp-socket-robustness
Open

Harden TCP/UDP socket loops and use RTHS-friendly network defaults#6
joecga4 wants to merge 1 commit into
aschellenberg74:masterfrom
joecga4:fix/tcp-udp-socket-robustness

Conversation

@joecga4

@joecga4 joecga4 commented Jul 6, 2026

Copy link
Copy Markdown

Port of the socket fixes already validated in OpenFresco's vendored copies of these files, applied to SRC/actor/channel.

Robustness (bug fixes)

  • The 9 recv/send loops in TCP_Socket never check the return value. If the peer closes, recv() returns 0 and the loop spins forever; on error (−1) nleft -= -1 grows the count and the data pointer moves backwards (memory corruption). All loops now treat <= 0 as an error and return −1, retry on EINTR, and the send paths restore the caller's byte-swapped data before bailing out.
  • Same treatment for the 8 recvfrom/sendto chunk loops in UDP_Socket, which now also advance by the actual byte count instead of the requested chunk size.
  • TCP_SocketSSL treated SSL_read() == 0 (clean shutdown) as success; checks are now <= 0.

Latency/reliability defaults (hybrid-simulation traffic is small request/response messages every integration step)

  • TCP_Socket/TCP_SocketSSL default to noDelay = 1. With Nagle + delayed-ACK a distributed hybrid test can stall ~40 ms per step. Callers passing noDelay explicitly are unaffected.
  • MAX_UDP_DATAGRAM 9126 → 1432 so one logical datagram fits in one MTU; at 9126 every datagram is IP-fragmented and one lost fragment drops the whole message. Both ends of a UDP channel must use the same value, so Socket.h, Socket.cpp and socket.c are kept in sync (OpenFresco ≥ 2026-07 already uses 1432).
  • UDP_Socket requests 512 KB SO_RCVBUF/SO_SNDBUF in its three constructors so per-step datagram bursts are not dropped.

Validation: full OpenSees suites green (pytest 7/7, verification 18/18 byte-identical, MP/SP/PyMP MPI runs); OneBayFrame distributed 3-process hybrid simulations against OpenFresco, including genericClientstartSimAppElemServer runs over both TCP and UDP (these exercise exactly this code), 1791 steps with outputs bit-identical across transports. In OpenFresco the same UDP changes measured max DAQ round-trip 1224 → 82 µs.

🤖 Generated with Claude Code

Robustness (bug fixes):
- The 9 recv/send loops in TCP_Socket never checked the return value.
  If the peer closes the connection recv() returns 0 and the loop spins
  forever; on error (-1) the pointer moves backwards and the byte count
  grows (memory corruption). All loops now treat <= 0 as an error and
  return -1, retry on EINTR, and the send paths restore the caller's
  byte-swapped data before bailing out.
- Same treatment for the 8 recvfrom/sendto chunk loops in UDP_Socket,
  which additionally advance by the actual byte count instead of the
  requested chunk size.
- TCP_SocketSSL treated SSL_read() == 0 (clean shutdown) as success and
  looped; the checks are now <= 0.

Latency/reliability defaults (hybrid simulation traffic is small
request/response messages exchanged every integration step):
- TCP_Socket/TCP_SocketSSL now default to noDelay = 1. With Nagle +
  delayed-ACK enabled a distributed hybrid test can stall ~40 ms per
  step. Callers that pass noDelay explicitly are unaffected.
- MAX_UDP_DATAGRAM 9126 -> 1432 so a logical datagram fits in one MTU;
  with 9126 every datagram is IP-fragmented and one lost fragment drops
  the whole message. Both ends of a UDP channel must use the same value
  (Socket.h, Socket.cpp and socket.c are kept in sync).
- UDP_Socket requests 512 KB SO_RCVBUF/SO_SNDBUF in its three
  constructors so per-step datagram bursts are not dropped.

These are ports of fixes validated in OpenFresco's vendored copies of
the same files (distributed 3-process hybrid simulations over TCP and
UDP, bit-identical outputs; measured max DAQ round-trip 1224 -> 82 us
after the UDP changes).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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