Skip to content

v2.4.2

Latest

Choose a tag to compare

@github-actions github-actions released this 13 Jul 18:32

Fixed

  • Made missing Stdin.FromFile sources reliably report ProcessError.Stdin when a child exits successfully.
  • Restored XPlat code-coverage collection for the C# test project in CI.
  • RunningProcess.StopAsync(gracePeriod) and ProcessGroup.ShutdownAsync(gracePeriod) now reject negative grace periods with ArgumentOutOfRangeException instead of silently treating them as an immediate kill.
  • On POSIX, process groups that reject a signal-0 liveness probe with EPERM are no longer treated as gone: they remain tracked for later control and teardown, while only ESRCH proves that a group no longer exists.
  • A Windows child spawned with StdioMode.Inherit (or Command.InheritStdin) no longer silently receives a handle to the parent process itself as its std input/output/error when the corresponding GetStdHandle fails. GetStdHandle returns INVALID_HANDLE_VALUE (-1) on failure, and to DuplicateHandle that -1 is the current-process pseudo-handle — the old check rejected only NULL, so -1 slipped through and duplicated the parent's full-access process handle into the child. Both failure sentinels are now rejected, so a broken GetStdHandle produces an honest ProcessError.Spawn instead.
  • Timeouts.raceTimeout now cancels the unused total-timeout timer as soon as an idle timeout wins, so long configured total deadlines no longer remain scheduled after the process has been timed out.
  • Exec.outputAll / Exec.outputAllBytes now cancel commands still waiting for a batch-concurrency slot immediately, while preserving results already completed before cancellation.
  • Command.Stdin(source) combined with Command.KeepStdinOpen() now works as documented instead of being a silent no-op. The stdin pipe is no longer force-closed once the source is exhausted: the source is fed first and the pipe is left open, and RunningProcess.TakeStdin then hands back a writable handle so the caller can keep writing to the same child interactively. The handle becomes available only after the background feeder has finished draining the source, so the source and the interactive writer never write the pipe at the same time. TakeStdin's wait for that feeder is deadlock-safe even when called from a single-threaded SynchronizationContext (a WPF/WinForms UI thread, classic ASP.NET): the feeder runs on the thread pool and never needs the caller's context to make progress. Both spawn paths (Command.StartAsync/ProcessGroup and the pipeline runner) close stdin after the source exactly as before when KeepStdinOpen is not set.
  • ProcessKit.Extensions.Hosting: a HostedProcessService.StopAsync call that found no active child to stop (supervision mid-backoff-sleep, or already ended) no longer resets LastStopOutcome to None, discarding a previous real stop's outcome; and a StopAsync whose internal stop wait was abandoned because the caller's cancellationToken expired first no longer risks an unobserved task exception if that abandoned stop later completes with a fault.