Skip to content

feat(python): outbound raw TCP/UDP sockets + complete the Pyodide FS hooks#142

Merged
NathanFlurry merged 2 commits into
mainfrom
python-sockets-and-fs-hooks
Jun 28, 2026
Merged

feat(python): outbound raw TCP/UDP sockets + complete the Pyodide FS hooks#142
NathanFlurry merged 2 commits into
mainfrom
python-sockets-and-fs-hooks

Conversation

@NathanFlurry

Copy link
Copy Markdown
Member

Two related pieces that finish out the guest-Python runtime, combined into one PR (two commits).

1. Raw TCP + UDP sockets

Backs Python's stdlib socket module with host sockets — same synchronous-bridge + network-policy model as the HTTP/DNS bridge.

  • Outbound TCP (connect/send/sendall/recv/close) and UDP (sendto/recvfrom/close), settimeout/setblocking.
  • Egress governed by require_network_access + the DNS egress guard (resolve-once-and-pin, restricted ranges refused).
  • Per-process host-socket registry; short read timeouts so a recv RPC never stalls the shared event loop (the Python shim re-polls to emulate blocking).
  • Listeners (bind/listen/accept) are out of scope — outbound only.

2. Complete the Emscripten FS hooks

Closes the remaining gaps so the custom FS backend implements every node_op/stream_op the FS layer dispatches (verified against MEMFS's ops_table).

  • symlink (was an ENOSYS stub) and readlink (was missing, no link-node) now work.
  • setattr now propagates chmod/chown/utimes to the host VFS (was in-isolate only).
  • Kernel-direct (no shadow mirror for create/modify) — mirroring would leave empty stubs that a later shadow→kernel sync resurrects over real content; the full suite caught + this avoids that.

Tests

  • python_runtime_supports_raw_tcp_and_udp_sockets — TCP + UDP echo servers through stdlib socket.
  • python_runtime_supports_symlink_readlink_and_metadataos.symlink/readlink/path.islink/chmod (host cross-checked)/utime.
  • Full python_suite stays green.

Supersedes #140 and #141 (closed in favor of this combined PR).

🤖 Generated with Claude Code

Back Python's socket module with host sockets (outbound TCP connect/send/recv,
UDP sendto/recvfrom), governed by the network policy + DNS egress guard like the
HTTP bridge:
- python.rs: SocketConnect/Send/Recv/Close + UdpCreate/Sendto/Recvfrom RPC methods,
  port/socketId wire fields, and Socket*/Udp* response payloads
- execution.rs: handle_python_socket_rpc_request opens host TcpStream/UdpSocket
  per process (require_network_access + filter_dns_safe_ip_addrs), short read
  timeout so a recv RPC never stalls the shared event loop
- state.rs: per-process PythonHostSocket registry
- runner: socket bridge methods + a socket.socket shim that polls recv/recvfrom
  to emulate blocking semantics

Listeners (bind/listen/accept) are out of scope — outbound only.

Test: python_runtime_supports_raw_tcp_and_udp_sockets drives TCP + UDP echo
servers through Python's stdlib socket module.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@railway-app

railway-app Bot commented Jun 28, 2026

Copy link
Copy Markdown

🚅 Deployed to the secure-exec-pr-142 environment in rivet-frontend

Service Status Web Updated (UTC)
secure-exec 😴 Sleeping (View Logs) Jun 28, 2026 at 2:47 am

🚅 Deployed to the secure-exec-pr-142 environment in secure-exec

Service Status Web Updated (UTC)
secure-exec 😴 Sleeping (View Logs) Web Jun 28, 2026 at 2:48 am

@NathanFlurry NathanFlurry force-pushed the python-sockets-and-fs-hooks branch from 456bcbc to 7a36a35 Compare June 28, 2026 02:10
@railway-app railway-app Bot temporarily deployed to rivet-frontend / secure-exec-pr-142 June 28, 2026 02:10 Destroyed
@railway-app railway-app Bot temporarily deployed to secure-exec / secure-exec-pr-142 June 28, 2026 02:10 Destroyed
FS hooks: symlink, readlink, lstat, and setattr->host (chmod/chown/utimes) —
every Emscripten node_op/stream_op. lstat lets pre-existing host symlinks be
detected as link nodes; setattr is host-first; chmod/utimes mirror to the host
shadow only when the entry already exists there (never creating empty stubs);
chown applies uid/gid independently (keeps the unchanged side).

Socket hardening: per-process registry bounded by the VM max_sockets limit,
read+write timeouts so recv/send can't wedge the shared loop (recv uses a short
host poll + a capped guest-side backoff), connect/sendto routed through the
loopback-connect gate (blocks DNS-rebind to sidecar-local ports), and host
errors mapped to the right OSError/errno.

Tests: python_runtime_supports_raw_tcp_and_udp_sockets,
python_runtime_supports_symlink_readlink_and_metadata (now also covers a
host-preexisting symlink); full python_suite green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@NathanFlurry NathanFlurry force-pushed the python-sockets-and-fs-hooks branch from 7a36a35 to 226624a Compare June 28, 2026 02:39
@railway-app railway-app Bot temporarily deployed to secure-exec / secure-exec-pr-142 June 28, 2026 02:39 Destroyed
@railway-app railway-app Bot temporarily deployed to rivet-frontend / secure-exec-pr-142 June 28, 2026 02:39 Destroyed
@NathanFlurry NathanFlurry merged commit 1107d7e into main Jun 28, 2026
3 of 4 checks passed
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