github.com/searKing/golang/go@v1.2.117/error/builtin/recover.go (about)

     1  // Copyright 2020 The searKing Author. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package builtin
     6  
     7  import (
     8  	"fmt"
     9  	"io"
    10  	"net"
    11  	"os"
    12  	"strings"
    13  	"time"
    14  )
    15  
    16  // The Recover function allows a program to manage behavior of a
    17  // panicking goroutine.
    18  // affect as recoverHandler(recover())
    19  // brokenPipeMsg is called when panic for broken pipe
    20  func Recover(writer io.Writer, recoverHandler func(err any) any, brokenPipeMsg func() string) any {
    21  	if err := recover(); err != nil {
    22  		// Check for a broken connection, as it is not really a
    23  		// condition that warrants a panic stack trace.
    24  		var brokenPipe = ErrorIsBrokenPipe(err)
    25  		if writer != nil {
    26  			goErr := fmt.Errorf("panic %v", err)
    27  
    28  			var msg string
    29  			if brokenPipeMsg != nil {
    30  				msg = brokenPipeMsg()
    31  			}
    32  
    33  			if brokenPipe {
    34  				_, _ = writer.Write([]byte(fmt.Sprintf("[Recovery] brokenPipe %+v\n%s", goErr, msg)))
    35  			} else {
    36  				_, _ = writer.Write([]byte(fmt.Sprintf("[Recovery] %s panic recovered:\n%+v",
    37  					timeFormat(time.Now()), goErr)))
    38  			}
    39  		}
    40  		if recoverHandler != nil {
    41  			return recoverHandler(err)
    42  		}
    43  		return err
    44  	}
    45  	return nil
    46  }
    47  func timeFormat(t time.Time) string {
    48  	var timeString = t.Format("2006/01/02 - 15:04:05")
    49  	return timeString
    50  }
    51  
    52  func ErrorIsBrokenPipe(err any) bool {
    53  	var brokenPipe bool
    54  	if ne, ok := err.(*net.OpError); ok {
    55  		if se, ok := ne.Err.(*os.SyscallError); ok {
    56  			if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
    57  				brokenPipe = true
    58  			}
    59  		}
    60  	}
    61  	return brokenPipe
    62  }