Skip to content

[Robustness] ProcessLauncher.cs — stdout/stderr log flush has no error handling, buffer lost on disk failure #770

@Christophe-Rogiers

Description

@Christophe-Rogiers

Severity: Warning

Location: src/Servy.Service/ProcessManagement/ProcessLauncher.cs:105-112

Code:

var encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); // UTF-8 without BOM

// Save logs if paths are set
if (!string.IsNullOrWhiteSpace(options.StdOutPath))
{
    File.AppendAllText(options.StdOutPath, stdoutBuffer.ToString(), encoding);
}
if (!string.IsNullOrWhiteSpace(options.StdErrPath))
{
    File.AppendAllText(options.StdErrPath, stderrBuffer.ToString(), encoding);
}

Explanation:
After a synchronous process launch, the captured stdout and stderr buffers are flushed to disk via File.AppendAllText with no try/catch. If the target path is unwritable (disk full, permission error, network path down, read-only attribute, file currently locked by another writer), the call throws an IOException / UnauthorizedAccessException that propagates out of ProcessLauncher.Start(...) — and the in-memory buffer is lost with the stack unwind.

This is exactly the scenario where the captured output matters most: a service is failing, its logs fill the buffer with the diagnostic evidence, and the very call that's supposed to persist that evidence throws — leaving the operator with no trace of what happened.

Suggested fix:
Wrap each AppendAllText in a try/catch, log the failure via logger.Error with the path and exception, and include a short prefix of the lost buffer in the log message so at least some evidence survives:

try
{
    File.AppendAllText(options.StdOutPath, stdoutBuffer.ToString(), encoding);
}
catch (Exception ex)
{
    logger.Error($"Failed to persist captured stdout to '{options.StdOutPath}': {ex.Message}. First 512 chars: {stdoutBuffer.ToString().Substring(0, Math.Min(512, stdoutBuffer.Length))}", ex);
}

Do not re-throw — the process has already run and the caller needs the IProcessWrapper return value regardless.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions