github.com/igggame/nebulas-go@v2.1.0+incompatible/cmd/neb/crashclient.go (about)

     1  // Copyright (C) 2017 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // the go-nebulas library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU General Public License
    16  // along with the go-nebulas library.  If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  
    19  package main
    20  
    21  import (
    22  	"fmt"
    23  	"math/rand"
    24  	"net"
    25  	"os"
    26  	"os/exec"
    27  	"path/filepath"
    28  	"strconv"
    29  	"syscall"
    30  
    31  	"github.com/nebulasio/go-nebulas/neblet/pb"
    32  	"github.com/nebulasio/go-nebulas/util/logging"
    33  	"github.com/sirupsen/logrus"
    34  )
    35  
    36  // InitCrashReporter init crash reporter
    37  func InitCrashReporter(conf *nebletpb.AppConfig) {
    38  	os.Setenv("GOBACKTRACE", "crash")
    39  	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
    40  	if err != nil {
    41  		logging.CLog().WithFields(logrus.Fields{
    42  			"err": err,
    43  		}).Fatal("Failed to init crash reporter.")
    44  	}
    45  	fp := fmt.Sprintf("%vcrash_%v.log", os.TempDir(), os.Getpid())
    46  
    47  	port := rand.Intn(0xFFFF-1024) + 1024
    48  	s, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
    49  
    50  	for i := 0; i < 0xff; i++ {
    51  		if err != nil {
    52  			port = rand.Intn(0xFFFF-1024) + 1024
    53  			s, err = net.Listen("tcp", fmt.Sprintf(":%d", port))
    54  		} else {
    55  			break
    56  		}
    57  	}
    58  
    59  	if err != nil {
    60  		logging.CLog().WithFields(logrus.Fields{
    61  			"err": err,
    62  		}).Fatal("Failed to init crash reporter.")
    63  	}
    64  	defer s.Close()
    65  
    66  	code := rand.Intn(0xFFFF)
    67  	cmd := exec.Command(fmt.Sprintf("%v/neb-crashreporter", dir),
    68  		"-logfile",
    69  		fp,
    70  		"-port",
    71  		strconv.Itoa(port),
    72  		"-code",
    73  		strconv.Itoa(code),
    74  		"-pid",
    75  		strconv.Itoa(os.Getpid()),
    76  		"-url",
    77  		conf.CrashReportUrl)
    78  
    79  	err = cmd.Start()
    80  	if err != nil {
    81  		logging.CLog().WithFields(logrus.Fields{
    82  			"err": err,
    83  		}).Fatal("Failed to start crash reporter daemon.")
    84  	}
    85  
    86  	conn, err := s.Accept()
    87  	if err != nil {
    88  		logging.CLog().WithFields(logrus.Fields{
    89  			"err": err,
    90  		}).Fatal("Failed to init crash reporter.")
    91  	}
    92  	var buf = make([]byte, 10)
    93  	n, berror := conn.Read(buf)
    94  	if berror != nil {
    95  		logging.CLog().WithFields(logrus.Fields{
    96  			"err": berror,
    97  		}).Fatal("Failed to read from conn")
    98  	}
    99  	rs := string(buf[:n])
   100  
   101  	if rs == strconv.Itoa(code) {
   102  		if crashFile, err := os.OpenFile(fp, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0664); err == nil {
   103  			os.Stderr = crashFile
   104  			syscall.Dup2(int(crashFile.Fd()), 2)
   105  		}
   106  	} else {
   107  		logging.CLog().WithFields(logrus.Fields{
   108  			"rs":   rs,
   109  			"code": code,
   110  			"err":  "code not match",
   111  		}).Fatal("Failed to init crash reporter.")
   112  	}
   113  
   114  	logging.CLog().Info("Started crash reporter.")
   115  }