From 2d711b70f6cdc6dc173902689c1deef64cf2e4e2 Mon Sep 17 00:00:00 2001 From: James Couball Date: Mon, 31 Aug 2026 15:37:26 -0700 Subject: [PATCH] docs: describe every source of MonitoredPipe#exception (#193) The docs for #exception said it holds "the exception raised by a destination", but the attribute records any failure while collecting output: a destination #write raising, the monitor loop raising, or pipe cleanup raising. A user inspecting the cause of a ProcessIOError was told a narrower story than the truth. Broaden the attribute docs and the matching class-level paragraph, and state two behaviors that were previously unwritten: the first recorded exception wins, and in the double-failure corner (monitor loop raises, then cleanup also raises) the cleanup error is the one recorded because the monitor-loop exception reaches its recording site last. The #close docs were verified against the issue's criteria and need no change; their wording is already source-neutral. No behavior change. --- lib/process_executer/monitored_pipe.rb | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/process_executer/monitored_pipe.rb b/lib/process_executer/monitored_pipe.rb index 1822cf4..14c07ac 100644 --- a/lib/process_executer/monitored_pipe.rb +++ b/lib/process_executer/monitored_pipe.rb @@ -44,9 +44,10 @@ module ProcessExecuter # a thread is created to read data written to the pipe. As data is read from the pipe, # it is written to the destination provided in the MonitoredPipe initializer. # - # If the destination raises an exception (of any class, not just - # `StandardError`), the monitoring thread will exit, the pipe will be closed, - # and the exception will be saved in `#exception`. + # If an exception (of any class, not just `StandardError`) is raised while + # collecting output -- by the destination's `#write`, by the monitor loop, + # or by pipe cleanup -- the monitoring thread exits, the pipe is closed, and + # the exception is saved in {#exception}. # # > **⚠️ WARNING** # > @@ -347,14 +348,22 @@ def write(data) # @!attribute [r] # - # The exception raised by a destination + # The first exception recorded while collecting output # - # If an exception is raised by a destination, it is stored here. Otherwise, it is `nil`. + # Any failure while collecting output is recorded here, not only a + # destination error: the destination's `#write` raising, the monitor loop + # raising, or pipe cleanup raising. `nil` if no exception was raised. + # + # When more than one exception is raised, the first one *recorded* wins + # and the rest are discarded. Recording order has one corner: when the + # monitor loop raises and pipe cleanup then also raises, the cleanup + # error is the one recorded, because the monitor-loop exception is still + # in flight while cleanup runs and reaches its recording site last. # # @example # pipe.exception #=> nil # - # @return [Exception, nil] the exception raised by a destination or `nil` if no exception was raised + # @return [Exception, nil] the first recorded exception or `nil` if no exception was raised # attr_reader :exception