From 6918412101f50a4f31a5f7d1d99e59b16dcc6c42 Mon Sep 17 00:00:00 2001 From: tannevaled Date: Fri, 13 Nov 2026 20:25:54 +0100 Subject: [PATCH 1/2] README: the Net::FTP hang figures describe code that has since changed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The map of where the work is said: The largest single debt is a hang, not a missing feature. Net::FTP alone is 442 examples behind, and 39 of its 56 spec files have to be killed by the clock on rbgo and none on MRI (#916). Re-measured today against MRI 4.0.6, same corpus, 30 s per file, on main at ba89ba6f: Net::FTP is 128 behind (459 -> 331) and NO file is killed at all. Only the figures this measurement actually covers are touched; the whole-corpus numbers above that bullet are left exactly as they were, because I have not re-swept the corpus. The replacement states the thing that took a day to establish and that a single number hides: ONE SYMPTOM, TWO UNRELATED CAUSES. Half the files hung because a blocking socket call held the emulated GVL (#924); the other half because TCPSocket.open with a block never closed the socket, so the peer waited for an EOF that never came (#932, open). Neither fix moves the other's files, which is why the first one looked like it had done nothing when it was measured against the second one's specs. The table also carries what is NOT fixed, with its cause named rather than left as a count: library/socket 8 and library/timeout 1, both because Thread#kill cannot interrupt a thread blocked in a native call (#933). A reader should be able to tell the fixed from the merely counted. ⛔ And the note that outlives all of these numbers: none of it was measurable until the reference interpreter was repaired. It had been scoring a clean 0 on every file because its bundled gems were off the load path, and a sweep reports that as a RESULT -- 56 files of "control 0 passing" reads as the implementation under test beating the reference. cmd/mriref (#930) is named so the next person measuring starts from a working oracle. Co-Authored-By: Claude Opus 5 --- README.md | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 732fedf4..89b5bde2 100644 --- a/README.md +++ b/README.md @@ -215,9 +215,26 @@ Three readings matter more than the total: `command_line/` files are built on `ruby_exe`, and the 46 `optional/capi/` files need a compiled C extension: **MRI itself scores 0** in them. That part of the corpus needs harness work, not interpreter work. -- **The largest single debt is a hang, not a missing feature.** `Net::FTP` alone - is 442 examples behind, and 39 of its 56 spec files have to be killed by the - clock on rbgo and none on MRI ([#916](https://github.com/go-embedded-ruby/ruby/issues/916)). +- **The hangs were the largest single debt, and most of them are gone** + ([#916](https://github.com/go-embedded-ruby/ruby/issues/916)). The run above + recorded `Net::FTP` 442 examples behind with 39 of its 56 files killed by the + clock. Re-measured on 2026-11-13 against MRI 4.0.6, same corpus, 30 s per + file: **`Net::FTP` is 128 behind (459 → 331) with no file killed at all.** + + One symptom, two unrelated causes, which is why the first fix looked like it + had done nothing when it was measured against the other half's specs: + + | | then | now | what it was | + | --- | --- | --- | --- | + | `library/net-ftp` | 39 killed | **0** | a blocking socket call held the emulated GVL | + | `library/net-http` | 27 killed | 27 | `TCPSocket.open { … }` never closed the socket, so the peer waited for an EOF that never came | + | `library/socket` | 8 killed | 8 | `Thread#kill` cannot interrupt a blocking native call | + | `library/timeout` | 1 killed | 1 | ditto | + + ⛔ None of this was measurable until the reference interpreter was repaired: + it had been scoring a clean **0** on every file because its bundled gems were + off the load path, which a sweep reports as a *result* rather than as a + broken instrument. See `cmd/mriref`. - **The rest is concentrated:** `matrix` 233, `bigdecimal` 180, `stringscanner` 154, `date`+`datetime` 179, `zlib` 130, `stringio` 94, `openssl` 93. The outright absences are small by comparison — `Coverage` 53, `StringScanner`'s From d2b8b2270f356048f483c7783a864bbd4cb92bf9 Mon Sep 17 00:00:00 2001 From: tannevaled Date: Sat, 14 Nov 2026 07:50:04 +0100 Subject: [PATCH 2/2] README: net-http is now 0 too, measured on the merged main #932 merged while this was in review, so the table's net-http row said 27 as the CURRENT figure for a module that no longer hangs at all. Publishing that would have been the same defect this pull request exists to correct. Re-measured on main at 6b51debe, 321 files across library/net-http + library/socket + library/timeout, MRI 4.0.6 as the control, 30 s per file: 275 passing against MRI's 371, NINE killed under rbgo and none under MRI. So the tally is 75 -> 9, and the nine are the last two rows: Thread#kill cannot interrupt a thread blocked in a native call (#933). Co-Authored-By: Claude Opus 5 --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 89b5bde2..0dc9cf86 100644 --- a/README.md +++ b/README.md @@ -227,10 +227,14 @@ Three readings matter more than the total: | | then | now | what it was | | --- | --- | --- | --- | | `library/net-ftp` | 39 killed | **0** | a blocking socket call held the emulated GVL | - | `library/net-http` | 27 killed | 27 | `TCPSocket.open { … }` never closed the socket, so the peer waited for an EOF that never came | + | `library/net-http` | 27 killed | **0** | `TCPSocket.open { … }` never closed the socket, so the peer waited for an EOF that never came | | `library/socket` | 8 killed | 8 | `Thread#kill` cannot interrupt a blocking native call | | `library/timeout` | 1 killed | 1 | ditto | + **75 → 9.** The nine that remain are the last two rows, measured the same way + on 2026-11-14: 321 files across those three modules, 275 passing against + MRI's 371, nine killed under rbgo and none under MRI. + ⛔ None of this was measurable until the reference interpreter was repaired: it had been scoring a clean **0** on every file because its bundled gems were off the load path, which a sweep reports as a *result* rather than as a