From d52e17e1117981765e1980c1ccc9e77d998a926c Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 5 Nov 2020 10:50:37 -0500 Subject: [PATCH] hide provider crashes from panicwrap when logging When logging is turned on, panicwrap will still see provider crashes and falsely report them as core crashes, hiding the formatted provider error. We can trick panicwrap by slightly obfuscating the error line. --- internal/logging/panic.go | 13 ++++++++++++- internal/logging/panic_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/internal/logging/panic.go b/internal/logging/panic.go index 960d4f685..211a1231d 100644 --- a/internal/logging/panic.go +++ b/internal/logging/panic.go @@ -172,11 +172,22 @@ func (l *logPanicWrapper) Debug(msg string, args ...interface{}) { // output if this is the start of the traceback. An occasional false // positive shouldn't be a big deal, since this is only retrieved after an // error of some sort. - l.inPanic = l.inPanic || strings.HasPrefix(msg, "panic: ") || strings.HasPrefix(msg, "fatal error: ") + + panicPrefix := strings.HasPrefix(msg, "panic: ") || strings.HasPrefix(msg, "fatal error: ") + + l.inPanic = l.inPanic || panicPrefix if l.inPanic && l.panicRecorder != nil { l.panicRecorder(msg) } + // If we have logging turned on, we need to prevent panicwrap from seeing + // this as a core panic. This can be done by obfuscating the panic error + // line. + if panicPrefix { + colon := strings.Index(msg, ":") + msg = strings.ToUpper(msg[:colon]) + msg[colon:] + } + l.Logger.Debug(msg, args...) } diff --git a/internal/logging/panic_test.go b/internal/logging/panic_test.go index e83a0ba5a..d2eb7a90b 100644 --- a/internal/logging/panic_test.go +++ b/internal/logging/panic_test.go @@ -1,9 +1,12 @@ package logging import ( + "bytes" "fmt" "strings" "testing" + + "github.com/hashicorp/go-hclog" ) func TestPanicRecorder(t *testing.T) { @@ -49,3 +52,31 @@ func TestPanicLimit(t *testing.T) { } } } + +func TestLogPanicWrapper(t *testing.T) { + var buf bytes.Buffer + logger := hclog.NewInterceptLogger(&hclog.LoggerOptions{ + Name: "test", + Level: hclog.Debug, + Output: &buf, + DisableTime: true, + }) + + wrapped := (&logPanicWrapper{ + Logger: logger, + }).Named("test") + + wrapped.Debug("panic: invalid foo of bar") + wrapped.Debug("\tstack trace") + + expected := `[DEBUG] test.test: PANIC: invalid foo of bar +[DEBUG] test.test: stack trace +` + + got := buf.String() + + if expected != got { + t.Fatalf("Expected:\n%q\nGot:\n%q", expected, got) + } + +}