Skip to content

docs: the Net::FTP worked example described code that has since changed - #926

Merged
tannevaled merged 1 commit into
mainfrom
docs-netftp-state
Nov 13, 2026
Merged

tannevaled merged 1 commit into
mainfrom
docs-netftp-state

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

docs: the Net::FTP worked example described code that has since changed

docs/SHARED-ENGINES.md's section "A deadline belongs to the engine's API,
not to its callers"
is the worked example carrying the whole shared-engine
argument. It described rbgo's binding, in the past tense, as calling
net.Dial with no timeout and setting no read deadline anywhere.

That was true when it was written. It is not true now — #921 is merged — and a
reader arriving at that page would conclude rbgo still has neither.

What is unchanged

The argument. An unbounded read in an engine four languages share is still a
shared denial of service, needing no exploit, only silence, and the neutral
engine should still take a deadline in its own API rather than trusting every
caller to impose one.

What is added

A dated subsection recording the consumer's half, because that is the part that
moved:

  • open_timeout (default nil, an unbounded connect) and read_timeout
    (default 60), read from the constructor's options Hash and from the attr
    writers, with the deadline armed per read rather than per exchange. A
    non-positive value means no bound, as in MRI — not "expire at once".
  • the GVL released around the control connection, plus the AST gate that refuses
    a new blocking socket call holding it (Net::FTP releases the GVL, and a gate so the next binding cannot forget #924), with the dose-response that
    turned the correlation into a mechanism (2 s → 2.308 s, 5 s → 5.307 s,
    ioBlock → 0.305 s).

⛔ And the honest limit, which is why the extraction warning stays

The measurement did not move. The library/net-ftp specs are byte-identical
after both changes: still 39 killed by the clock, still 459/17, still −442. Both
fixes are necessary and proved on a minimal reproduction, but at least one cause
remains and it is in the spec-harness path.

The three candidates eliminated so far are named on the page, together with
how they were eliminated — by reading rather than by timing, because the
machine was carrying a load average of 23–86 and a timeout measured under that
cannot tell a hang from a slow file.

Writing "fixed" here while the number sits where it was is exactly how a docs
page stops being evidence.

Refs #916

🤖 Generated with Claude Code

…changed

The "a deadline belongs to the engine's API" section is the worked example
for the whole shared-engine argument, and it described the binding in the
past tense as having no timeout and no read deadline "anywhere". That was
true when it was written and is not true now: #921 is merged. A reader
arriving at that page would conclude rbgo still has neither.

The argument is unchanged -- an unbounded read in an engine four languages
share is still a shared denial of service, and the neutral engine should
still take a deadline in its own API. What changed is the consumer's half,
so that is what the new subsection records:

  - open_timeout (default nil, unbounded) and read_timeout (default 60),
    from the options Hash and from the attr writers, with the deadline armed
    PER READ. Non-positive means no bound, as in MRI.
  - the GVL released around the control connection, plus an AST gate that
    refuses a new blocking socket call holding it (#924), with the
    dose-response that proved the mechanism.

⛔ And the honest limit, which is the reason the extraction warning STAYS:
the measurement did not move. The library/net-ftp specs are byte-identical
after both changes -- still 39 killed, 459/17, -442. Both fixes are
necessary and proved on a minimal reproduction, but at least one cause
remains and it is in the spec-harness path. The three candidates eliminated
so far are named, with how they were eliminated (by reading, not by timing,
since the machine was too loaded for a timeout to mean anything).

Writing "fixed" here while the number sits where it was is exactly how a
docs page stops being evidence.

Refs #916

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit 209fa06 into main Nov 13, 2026
26 checks passed
@tannevaled
tannevaled deleted the docs-netftp-state branch November 13, 2026 12:21
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