tar/asm: add NewInputTarStreamWithDone + tests#86
tar/asm: add NewInputTarStreamWithDone + tests#86jankaluza wants to merge 1 commit intovbatts:mainfrom
Conversation
|
@mtrmac , can you please check this when you have time? :-) |
mtrmac
left a comment
There was a problem hiding this comment.
A fairly quick look. I didn’t read the tests at all yet.
Is there a corresponding consumer PR to prove the concept and demonstrate how the API is used?
Nothing in the commit / comments says why we need it, and I think it’s important to preserve that knowledge. (The PR description does link to a part of the motivation, but that’s not going to be obvious to people just reading the code.)
-
Whether processing the tar stream succeeds, fails inside tar-split, or fails in the consumer of tar-split, we need an ability to block until the goroutine terminates (and the input
rreader is safe to deallocate / reuse). I think thedonechannel works fine for that. -
If processing the tar stream fails in the consumer of tar-split, and that consumer aborts, the consumer does not want to read all of the tar to completion. In that case, the current code’s goroutine will just hang trying to write to an abandoned pipe, and keep memory allocated forever.
- Returning a
ReadCloserand having theClosesignal an abort works (unlike using aContext, which can’t abort a pipe write). - I wonder about directly returning a
PipeReader. That might allow the consumer to useCloseWithErrorand potentially allow better diagnostics, OTOH the goroutine is not currently logging anything anyway — and returning aPipeReaderwould be more of an API commitment. I don’t have a strong opinion. - In both of the callers in c/storage, if consuming the tar from this function fails, nothing uses the data produced by
storage.Packer. So I don’t think thebestEffortPipeWriteris necessary — it’s actually unwanted for us, because the goroutine will continue consuming the input and burning I/O or CPU (and blocking the caller who just wants adonesignal and terminate), for no benefit. It would be better if the goroutine saw the pipe write fail, and terminated.
- Returning a
39ff334 to
153c68f
Compare
Refactor tar disassembly into a shared `runInputTarStream`, `runInputTarStreamGoroutine` and `newInputTarStreamCommon` setup helper. Add `NewInputTarStreamWithDone`, which returns an `io.ReadCloser` together with a `done` channel that is signaled when the internal goroutine finishes (or fails), including the final padding-draining phase. Preserve existing `NewInputTarStream` behavior and API. Add unit tests covering: - successful full reads - early consumer close - packer error propagation - underlying reader failure while the tar-split goroutine is still running Motivation: callers need a reliable way to (1) abort consumption when they fail early and (2) block until the background goroutine has terminated so the underlying input reader can be safely released/reused. The wrapper guarantees the protocol (close pipe + send exactly one done value) even on panics, while preserving prompt termination when the consumer closes early. Relates: containers/container-libs#148 Signed-off-by: Jan Kaluza <[email protected]>
153c68f to
915b1a6
Compare
|
@mtrmac , example of this code in use is here: https://github.com/containers/podman/pull/28018/changes#diff-1169f6e33aa043d846707f96a461aedef54252acc9290f5e5e2c64cce0c2920f |
Refactor tar disassembly into a shared
runInputTarStreamgoroutine andnewInputTarStreamCommonsetup helper.Introduce
bestEffortPipeWriterto allow tar parsing and metadata packing to complete even if the consumer closes the pipe early.Add
NewInputTarStreamWithDone, which returns anio.ReadClosertogether with adonechannel that is signaled when the internal goroutine finishes (or fails), including the final padding-draining phase.Preserve existing
NewInputTarStreambehavior and API.Add unit tests covering:
This is needed to fix containers/container-libs#148. Please check this ticket for more context.