forked from cockroachdb/cockroach
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
114759: server: fix error handling in status server GetFiles r=xinhaoz a=xinhaoz Previously, we ignored errors returned by the stat file call in status server's `GetFiles`. This can lead to a panic if the stat call returns an error as we dereference the nil file info object later on without any guards. This commit patches the nil pointer dereference by returning any error encountered by stat immediately. Note that in the future we should probably change this to just ignore the current file path and continue with the rest of the files in the list. However, this is a good first patch to minimize backported code changes. Fixes: cockroachdb#114453 Release note (bug fix): GetFiles should not cause a nil pointer dereference. Co-authored-by: Xin Hao Zhang <[email protected]>
- Loading branch information
Showing
4 changed files
with
112 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// Copyright 2023 The Cockroach Authors. | ||
// | ||
// Use of this software is governed by the Business Source License | ||
// included in the file licenses/BSL.txt. | ||
// | ||
// As of the Change Date specified in that file, in accordance with | ||
// the Business Source License, use of this software will be governed | ||
// by the Apache License, Version 2.0, included in the file | ||
// licenses/APL.txt. | ||
|
||
package server | ||
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/cockroachdb/cockroach/pkg/server/serverpb" | ||
"github.com/cockroachdb/cockroach/pkg/testutils" | ||
"github.com/cockroachdb/cockroach/pkg/util/leaktest" | ||
"github.com/cockroachdb/cockroach/pkg/util/log" | ||
"github.com/cockroachdb/errors" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
// TestGetLocalFiles tests that retrieving local heap and goroutine profiles | ||
// returns and reads files when they exist and returns the expected error | ||
// when the file on encountered errors. | ||
// Note that there is more extensive end to end testing of this done in | ||
// pkg/server/storage_api/files_test.go. This test was created to test the | ||
// error handling in response to #114453. | ||
func TestGetLocalFiles(t *testing.T) { | ||
defer leaktest.AfterTest(t)() | ||
defer log.Scope(t).Close(t) | ||
|
||
// We'll read a file successfully first to ensure the read logic is working. | ||
tempDir, cleanupFn := testutils.TempDir(t) | ||
defer cleanupFn() | ||
|
||
testHeapDir := filepath.Join(tempDir, "heap_profiles") | ||
if err := os.MkdirAll(testHeapDir, os.ModePerm); err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
t.Run("read files successfully", func(t *testing.T) { | ||
testHeapFile := filepath.Join(testHeapDir, "im-in-the-heap-dir") | ||
if err := os.WriteFile(testHeapFile, []byte("heap stuff"), 0644); err != nil { | ||
t.Fatal(err) | ||
} | ||
req := &serverpb.GetFilesRequest{ | ||
NodeId: "local", Type: serverpb.FileType_HEAP, Patterns: []string{"*"}} | ||
res, err := getLocalFiles(req, testHeapDir, "", os.Stat, os.ReadFile) | ||
require.NoError(t, err) | ||
require.Equal(t, 1, len(res.Files)) | ||
require.Equal(t, "im-in-the-heap-dir", res.Files[0].Name) | ||
}) | ||
|
||
t.Run("stat file error", func(t *testing.T) { | ||
testHeapFile := filepath.Join(testHeapDir, "im-in-the-heap-dir") | ||
if err := os.WriteFile(testHeapFile, []byte("heap stuff"), 0644); err != nil { | ||
t.Fatal(err) | ||
} | ||
// Test that getLocalFiles returns an error when the file cannot be read with stat. | ||
statFileWithErr := func(name string) (os.FileInfo, error) { | ||
return nil, errors.Errorf("stat error") | ||
} | ||
req := &serverpb.GetFilesRequest{ | ||
NodeId: "local", Type: serverpb.FileType_HEAP, Patterns: []string{"*"}} | ||
_, err := getLocalFiles(req, testHeapDir, "", statFileWithErr, os.ReadFile) | ||
require.ErrorContains(t, err, "stat error") | ||
}) | ||
|
||
t.Run("read file error", func(t *testing.T) { | ||
testHeapFile := filepath.Join(testHeapDir, "im-in-the-heap-dir") | ||
if err := os.WriteFile(testHeapFile, []byte("heap stuff"), 0644); err != nil { | ||
t.Fatal(err) | ||
} | ||
// Test that getLocalFiles returns an error when the file cannot be read. | ||
readFileWithErr := func(name string) ([]byte, error) { | ||
return nil, errors.Errorf("read error") | ||
} | ||
req := &serverpb.GetFilesRequest{ | ||
NodeId: "local", Type: serverpb.FileType_HEAP, Patterns: []string{"*"}} | ||
_, err := getLocalFiles(req, testHeapDir, "", os.Stat, readFileWithErr) | ||
require.ErrorContains(t, err, "read error") | ||
}) | ||
|
||
t.Run("dirs not implemented", func(t *testing.T) { | ||
req := &serverpb.GetFilesRequest{ | ||
NodeId: "local", Type: serverpb.FileType_HEAP, Patterns: []string{"*"}} | ||
_, err := getLocalFiles(req, "", "nonexistent", os.Stat, os.ReadFile) | ||
require.ErrorContains(t, err, "dump directory not configured") | ||
|
||
req = &serverpb.GetFilesRequest{ | ||
NodeId: "local", Type: serverpb.FileType_GOROUTINES, Patterns: []string{"*"}} | ||
_, err = getLocalFiles(req, "nonexistent", "", os.Stat, os.ReadFile) | ||
require.ErrorContains(t, err, "dump directory not configured") | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters