From 83b2e17d4854f74036ca72b133c201dc275bc0b6 Mon Sep 17 00:00:00 2001 From: joerger Date: Thu, 11 Dec 2025 11:16:57 -0800 Subject: [PATCH 1/5] Significantly speed up TestChaosUpload with a more aggressive scan period. --- lib/events/filesessions/fileasync_chaos_test.go | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/lib/events/filesessions/fileasync_chaos_test.go b/lib/events/filesessions/fileasync_chaos_test.go index 943e7b1775ddf..3452a9b8f1e56 100644 --- a/lib/events/filesessions/fileasync_chaos_test.go +++ b/lib/events/filesessions/fileasync_chaos_test.go @@ -1,5 +1,3 @@ -//go:build !race - /* * Teleport * Copyright (C) 2023 Gravitational, Inc. @@ -41,15 +39,7 @@ import ( // TestChaosUpload introduces failures in all stages of the async // upload process and verifies that the system is working correctly. -// -// Data race detector slows down the test significantly (10x+), -// that is why the test is skipped when tests are running with -// `go test -race` flag or `go test -short` flag func TestChaosUpload(t *testing.T) { - if testing.Short() { - t.Skip("Skipping chaos test in short mode.") - } - ctx := t.Context() eventsC := make(chan events.UploadEvent, 100) @@ -114,7 +104,7 @@ func TestChaosUpload(t *testing.T) { uploader, err := NewUploader(UploaderConfig{ ScanDir: scanDir, CorruptedDir: corruptedDir, - ScanPeriod: 3 * time.Second, + ScanPeriod: 100 * time.Millisecond, Streamer: faultyStreamer, Clock: clockwork.NewRealClock(), }) From 4585aa9278411c8dbebb26d280d1fb23343d0db9 Mon Sep 17 00:00:00 2001 From: joerger Date: Thu, 11 Dec 2025 16:30:10 -0800 Subject: [PATCH 2/5] Add missing close for encrypted upload error. --- lib/events/filesessions/fileasync.go | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/events/filesessions/fileasync.go b/lib/events/filesessions/fileasync.go index 6e29e2cce46eb..93c45ac577bdc 100644 --- a/lib/events/filesessions/fileasync.go +++ b/lib/events/filesessions/fileasync.go @@ -588,6 +588,7 @@ func (u *Uploader) startUpload(ctx context.Context, fileName string) (err error) Error: err, Created: u.cfg.Clock.Now().UTC(), }) + upload.Close() return trace.Wrap(err) } } else { From 59ac781d8d7e6eebf5cd5b91e8f0f593df2ae048 Mon Sep 17 00:00:00 2001 From: joerger Date: Thu, 11 Dec 2025 16:51:09 -0800 Subject: [PATCH 3/5] Don't treat empty uploads as a session error. --- lib/events/filesessions/fileasync.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/events/filesessions/fileasync.go b/lib/events/filesessions/fileasync.go index 93c45ac577bdc..a9d2286671519 100644 --- a/lib/events/filesessions/fileasync.go +++ b/lib/events/filesessions/fileasync.go @@ -636,6 +636,10 @@ func (u *Uploader) uploadEncrypted(ctx context.Context, up *upload) error { log := u.log.With(fieldSessionID, up.sessionID) header, err := events.ParsePartHeader(up.file) if err != nil { + // Empty upload files are not treated as a session error. + if errors.Is(err, io.EOF) { + return trace.Wrap(err) + } return trace.Wrap(sessionError{err}) } @@ -769,6 +773,7 @@ func (u *Uploader) upload(ctx context.Context, up *upload) error { for { event, err := up.reader.Read(ctx) if err != nil { + // Note that empty upload files are not treated as a session error. if errors.Is(err, io.EOF) { break } From af921c2229c2cfac27eb443c9f063bacf200bb11 Mon Sep 17 00:00:00 2001 From: joerger Date: Fri, 12 Dec 2025 10:19:04 -0800 Subject: [PATCH 4/5] Defer close. --- lib/events/filesessions/fileasync.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/events/filesessions/fileasync.go b/lib/events/filesessions/fileasync.go index a9d2286671519..939c6e73f4aa2 100644 --- a/lib/events/filesessions/fileasync.go +++ b/lib/events/filesessions/fileasync.go @@ -581,6 +581,14 @@ func (u *Uploader) startUpload(ctx context.Context, fileName string) (err error) reader: nil, } + defer func() { + if err != nil { + if err := upload.Close(); err != nil { + log.WarnContext(ctx, "Failed to close upload.", "error", err) + } + } + }() + if err := u.uploadEncrypted(ctx, upload); err != nil { if !errors.Is(err, errSkipEncryptedUpload) { u.emitEvent(events.UploadEvent{ @@ -588,7 +596,6 @@ func (u *Uploader) startUpload(ctx context.Context, fileName string) (err error) Error: err, Created: u.cfg.Clock.Now().UTC(), }) - upload.Close() return trace.Wrap(err) } } else { @@ -605,9 +612,6 @@ func (u *Uploader) startUpload(ctx context.Context, fileName string) (err error) upload.checkpointFile, err = os.OpenFile(u.checkpointFilePath(sessionID), os.O_RDWR|os.O_CREATE, 0o600) if err != nil { - if err := upload.Close(); err != nil { - log.WarnContext(ctx, "Failed to close upload.", "error", err) - } return trace.ConvertSystemError(err) } From 8ff08e1178aa5214d6a86456fddf695d33987c28 Mon Sep 17 00:00:00 2001 From: joerger Date: Fri, 12 Dec 2025 10:54:57 -0800 Subject: [PATCH 5/5] Add comment. --- lib/events/filesessions/fileasync.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/events/filesessions/fileasync.go b/lib/events/filesessions/fileasync.go index 939c6e73f4aa2..cf78751645f15 100644 --- a/lib/events/filesessions/fileasync.go +++ b/lib/events/filesessions/fileasync.go @@ -582,6 +582,9 @@ func (u *Uploader) startUpload(ctx context.Context, fileName string) (err error) } defer func() { + // If we get an error, that signals that the upload goroutine (encrypted or nonencrypted) + // failed to start, so we must manually close the upload as the defers in the goroutine will + // never be called. if err != nil { if err := upload.Close(); err != nil { log.WarnContext(ctx, "Failed to close upload.", "error", err)