When starting metric profiling, truncate existing profile log if applicable.

Prior to this change, if `runsc` was configured to use a specific
`--profiling-metrics-log` path, then the second run of this runtime would
overwrite existing metric data in-place, which produces a corrupt file.

This change truncates the existing log, so that the resulting log actually
correspond to what just ran.

This only happens when the `os.File` supports `truncate(2)`, which stdout
does not, so the error is ignored if there is one. It's a best-effort thing.

PiperOrigin-RevId: 648493697
This commit is contained in:
Etienne Perot
2024-07-01 14:55:08 -07:00
committed by gVisor bot
parent 090d9a33d4
commit d436e16e6b
+20
View File
@@ -99,6 +99,9 @@ type ProfilingMetricsWriter interface {
// WriteString from the io.StringWriter interface.
io.StringWriter
// Truncate truncates the underlying writer, if possible.
Truncate(size int64) error
// Close closes the writer.
Close() error
}
@@ -198,6 +201,13 @@ func StartProfilingMetrics[T ProfilingMetricsWriter](opts ProfilingMetricsOption
s.ringbuffer[i] = make([]uint64, snapshotBufferSize*(numMetrics+1))
}
// Truncate the underlying sink if possible to delete any past profiling
// data in the file, if any, as it makes no sense to concatenate them or
// to overwrite them in-place.
// We ignore errors here because the sink may not be truncatable,
// e.g. when it is pointing to the stdout FD.
_ = opts.Sink.Truncate(0)
stopProfilingMetrics = atomicbitops.FromBool(false)
doneProfilingMetrics = make(chan bool, 1)
writeCh := make(chan writeReq, snapshotRingbufferSize)
@@ -377,6 +387,11 @@ func (w *bufferedWriter[T]) Flush() {
w.buf.Reset()
}
// Truncate implements bufferedMetricsWriter.Truncate.
func (w *bufferedWriter[T]) Truncate(size int64) error {
return w.underlying.Truncate(size)
}
// Close implements bufferedMetricsWriter.Close.
func (w *bufferedWriter[T]) Close() error {
w.Flush()
@@ -479,6 +494,11 @@ func (w *lossyBufferedWriter[T]) NewLine() {
}
}
// Truncate implements bufferedMetricsWriter.Truncate.
func (w *lossyBufferedWriter[T]) Truncate(size int64) error {
return w.underlying.Truncate(size)
}
// Close implements bufferedMetricsWriter.Close.
// It writes the checksum of the data written to the underlying writer.
func (w *lossyBufferedWriter[T]) Close() error {