github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/cmd/utils/cmd.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package utils contains internal helper functions for go-ethereum commands. 18 package utils 19 20 import ( 21 "fmt" 22 "io" 23 "os" 24 "os/signal" 25 "runtime" 26 "syscall" 27 "time" 28 29 "gopkg.in/urfave/cli.v1" 30 31 "github.com/unicornultrafoundation/go-u2u/common" 32 "github.com/unicornultrafoundation/go-u2u/eth/ethconfig" 33 "github.com/unicornultrafoundation/go-u2u/internal/debug" 34 "github.com/unicornultrafoundation/go-u2u/log" 35 "github.com/unicornultrafoundation/go-u2u/node" 36 ) 37 38 const ( 39 importBatchSize = 2500 40 ) 41 42 // Fatalf formats a message to standard error and exits the program. 43 // The message is also printed to standard output if standard error 44 // is redirected to a different file. 45 func Fatalf(format string, args ...interface{}) { 46 w := io.MultiWriter(os.Stdout, os.Stderr) 47 if runtime.GOOS == "windows" { 48 // The SameFile check below doesn't work on Windows. 49 // stdout is unlikely to get redirected though, so just print there. 50 w = os.Stdout 51 } else { 52 outf, _ := os.Stdout.Stat() 53 errf, _ := os.Stderr.Stat() 54 if outf != nil && errf != nil && os.SameFile(outf, errf) { 55 w = os.Stderr 56 } 57 } 58 fmt.Fprintf(w, "Fatal: "+format+"\n", args...) 59 os.Exit(1) 60 } 61 62 func StartNode(ctx *cli.Context, stack *node.Node) { 63 if err := stack.Start(); err != nil { 64 Fatalf("Error starting protocol stack: %v", err) 65 } 66 go func() { 67 sigc := make(chan os.Signal, 1) 68 signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM) 69 defer signal.Stop(sigc) 70 71 minFreeDiskSpace := ethconfig.Defaults.TrieDirtyCache 72 if ctx.GlobalIsSet(MinFreeDiskSpaceFlag.Name) { 73 minFreeDiskSpace = ctx.GlobalInt(MinFreeDiskSpaceFlag.Name) 74 } else { 75 minFreeDiskSpace = 8192 76 } 77 if minFreeDiskSpace > 0 { 78 go monitorFreeDiskSpace(sigc, stack.InstanceDir(), uint64(minFreeDiskSpace)*1024*1024) 79 } 80 81 <-sigc 82 log.Info("Got interrupt, shutting down...") 83 go stack.Close() 84 for i := 10; i > 0; i-- { 85 <-sigc 86 if i > 1 { 87 log.Warn("Already shutting down, interrupt more to panic.", "times", i-1) 88 } 89 } 90 debug.Exit() // ensure trace and CPU profile data is flushed. 91 debug.LoudPanic("boom") 92 }() 93 } 94 95 func monitorFreeDiskSpace(sigc chan os.Signal, path string, freeDiskSpaceCritical uint64) { 96 for { 97 freeSpace, err := GetFreeDiskSpace(path) 98 if err != nil { 99 log.Warn("Failed to get free disk space", "path", path, "err", err) 100 break 101 } 102 if freeSpace < freeDiskSpaceCritical { 103 log.Error("Low disk space. Gracefully shutting down client to prevent database corruption.", "available", common.StorageSize(freeSpace)) 104 sigc <- syscall.SIGTERM 105 break 106 } else if freeSpace < 2*freeDiskSpaceCritical { 107 log.Warn("Disk space is running low. client will shutdown if disk space runs below critical level.", "available", common.StorageSize(freeSpace), "critical_level", common.StorageSize(freeDiskSpaceCritical)) 108 } 109 time.Sleep(60 * time.Second) 110 } 111 }