Repository navigation
feat(system): sockets() — which process holds that port (S2) - #89
Merged
Merged
Conversation
SELECT * FROM sockets() WHERE state = 'LISTEN', joined to processes() on pid through CTEs. An ordinary TableGenerator beside processes(), reading the OS's own socket tables through netstat2: GetExtendedTcpTable and GetExtendedUdpTable on Windows, netlink sock_diag plus /proc/*/fd on Linux, libproc on macOS. Nothing is resolved to a hostname. Reverse DNS is what makes `netstat -a` take seconds on Windows; the table itself comes back in ~6 ms over 204 sockets here, and ~3 ms on Linux. Eight columns, identical on every platform: protocol, family, local_address, local_port, remote_address, remote_port, state, pid. One row per (socket, pid); a socket with no visible owner still gets one row with a NULL pid. State uses the RFC 793 names, with Windows' DELETE_TCB mapped to CLOSED. Two absences come out as NULL rather than plausible values: - UDP and listening TCP sockets have no far end, which the OS reports as 0.0.0.0:0. Those are NULL remote columns. - Windows gives pid 0 to sockets whose process has exited (every TIME_WAIT row here), and processes() lists pid 0 as Idle. Passing it through would have made the join blame the idle process. Tested on Windows 11 and on Ubuntu under WSL2, where the build needs no libclang (netstat2 only runs bindgen on macOS). As root on Linux the join agrees with `ss -tulpn`; sockets owned by other WSL distributions sharing the network namespace stay NULL there, as they do for ss. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
sockets(), the second system table (S2 indocs/SYSTEM_TABLES.md): every TCP and UDP socket on the machine with its owning pid, so it joins toprocesses().netstat -ais slow because it looks up a hostname for every address.sockets()never does: it reads the OS socket tables directly throughnetstat2(GetExtendedTcpTable/GetExtendedUdpTableon Windows, netlinksock_diag+/proc/*/fdon Linux). About 6 ms for 204 sockets on Windows, 3 ms on Linux.protocol,family,local_address,local_port,remote_address,remote_port,state,pid. One row per (socket, pid). A socket with no visible owner still gets a row, with a NULL pid.0.0.0.0/0.processes()lists pid 0 asIdle, so the join would otherwise blame the Idle process.DELETE_TCBmaps toCLOSED.system-tablesfeature. Includesexamples/system_sockets.sql(7 queries) and the S2 write-up.Test plan
cargo test --releaseon Windows 11: all pass. New tests open their own listener, connection and UDP socket and check each row; pid handling has its own unit test.ss -tulpnas root and as a normal user.examples/system_sockets.sqlpasses viatests/integration/test_examples.py.cargo fmt --check, clippy clean forsystem.rs.--no-default-features --features redis-cachecompiles. Plain--no-default-featuresalready fails on main because of aRedisCacheimport insrc/main_handlers.rs, unrelated to this PR.🤖 Generated with Claude Code