Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capturing panic() in golang

Tags:

We have a large-ish golang application that uses the logger (actually, a custom logger), to write output to a log file that is periodically rotated.

However, when an application crashes or panic()'s, those messages go to standard error.

Is there any way to override the panic functionality to use our logger?

like image 251
David Frascone Avatar asked Jan 13 '16 16:01

David Frascone


People also ask

How do you capture panic in Golang?

The Go paradigm is to check for errors explicitly. A program should only panic if the circumstances under which it panics do not happen during ordinary program executing. For instance, not being able to open a file is something that can happen and should not cause a panic while running out of memory is worth a panic.

What does panic in Golang do?

What is panic() in Golang? The panic() function in Go Language is similar to exceptions raised at runtime when an error is encountered. panic() is either raised by the program itself when an unexpected error occurs or the programmer throws the exception on purpose for handling particular errors.

How do you recover in Golang?

The recover() function only works if it is called in the goroutine where panic() occurs. The recover() function only works when called in a deferred function. This is because when a panic occurs, deferred functions do not exit or crash as a normal function would.

How do you catch exceptions in Golang?

This method is also known as try-catch-finally In this method, in the try block the error-free code has been executed and if it has found some issue it will be handled in the catch block and finally block will be executed all the things at any cost.


1 Answers

As far as I know, you can't redirect the output from panic away from standard error, or to your logger. The best thing you can do is redirect standard error to a file which you can do externally, or inside your program.

For my rclone program I redirected standard error to capture everything to a file on an option which is unfortunately isn't particularly easy to do in a cross platform way. Here is how I did it (see the redirect*.go files)

For linux/unix

// Log the panic under unix to the log file  //+build unix  package main  import (     "log"     "os"     "syscall" )  // redirectStderr to the file passed in func redirectStderr(f *os.File) {     err := syscall.Dup2(int(f.Fd()), int(os.Stderr.Fd()))     if err != nil {         log.Fatalf("Failed to redirect stderr to file: %v", err)     } } 

and for windows

// Log the panic under windows to the log file // // Code from minix, via // // http://play.golang.org/p/kLtct7lSUg  //+build windows  package main  import (     "log"     "os"     "syscall" )  var (     kernel32         = syscall.MustLoadDLL("kernel32.dll")     procSetStdHandle = kernel32.MustFindProc("SetStdHandle") )  func setStdHandle(stdhandle int32, handle syscall.Handle) error {     r0, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0)     if r0 == 0 {         if e1 != 0 {             return error(e1)         }         return syscall.EINVAL     }     return nil }  // redirectStderr to the file passed in func redirectStderr(f *os.File) {     err := setStdHandle(syscall.STD_ERROR_HANDLE, syscall.Handle(f.Fd()))     if err != nil {         log.Fatalf("Failed to redirect stderr to file: %v", err)     }     // SetStdHandle does not affect prior references to stderr     os.Stderr = f } 
like image 64
Nick Craig-Wood Avatar answered Sep 28 '22 02:09

Nick Craig-Wood