cmd/geth, cmd/utils: improve interrupt handling

The new strategy for interrupts is to handle them explicitly.
Ethereum.Stop is now only called once, even if multiple interrupts
are sent. Interrupting ten times in a row forces a panic.

Fixes #869
Fixes #1359
This commit is contained in:
Felix Lange 2015-07-06 15:01:13 +02:00
parent aa4502060b
commit 5615fc4714
2 changed files with 17 additions and 37 deletions

View File

@ -347,7 +347,6 @@ func main() {
} }
func run(ctx *cli.Context) { func run(ctx *cli.Context) {
utils.HandleInterrupt()
cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx) cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
ethereum, err := eth.New(cfg) ethereum, err := eth.New(cfg)
if err != nil { if err != nil {
@ -527,10 +526,9 @@ func blockRecovery(ctx *cli.Context) {
func startEth(ctx *cli.Context, eth *eth.Ethereum) { func startEth(ctx *cli.Context, eth *eth.Ethereum) {
// Start Ethereum itself // Start Ethereum itself
utils.StartEthereum(eth) utils.StartEthereum(eth)
am := eth.AccountManager()
am := eth.AccountManager()
account := ctx.GlobalString(utils.UnlockedAccountFlag.Name) account := ctx.GlobalString(utils.UnlockedAccountFlag.Name)
accounts := strings.Split(account, " ") accounts := strings.Split(account, " ")
for i, account := range accounts { for i, account := range accounts {

View File

@ -46,29 +46,6 @@ const (
var interruptCallbacks = []func(os.Signal){} var interruptCallbacks = []func(os.Signal){}
// Register interrupt handlers callbacks
func RegisterInterrupt(cb func(os.Signal)) {
interruptCallbacks = append(interruptCallbacks, cb)
}
// go routine that call interrupt handlers in order of registering
func HandleInterrupt() {
c := make(chan os.Signal, 1)
go func() {
signal.Notify(c, os.Interrupt)
for sig := range c {
glog.V(logger.Error).Infof("Shutting down (%v) ... \n", sig)
RunInterruptCallbacks(sig)
}
}()
}
func RunInterruptCallbacks(sig os.Signal) {
for _, cb := range interruptCallbacks {
cb(sig)
}
}
func openLogFile(Datadir string, filename string) *os.File { func openLogFile(Datadir string, filename string) *os.File {
path := common.AbsolutePath(Datadir, filename) path := common.AbsolutePath(Datadir, filename)
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
@ -149,19 +126,24 @@ func StartEthereum(ethereum *eth.Ethereum) {
if err := ethereum.Start(); err != nil { if err := ethereum.Start(); err != nil {
Fatalf("Error starting Ethereum: %v", err) Fatalf("Error starting Ethereum: %v", err)
} }
RegisterInterrupt(func(sig os.Signal) { go func() {
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, os.Interrupt)
defer signal.Stop(sigc)
<-sigc
glog.V(logger.Info).Infoln("Got interrupt, shutting down...")
ethereum.Stop() ethereum.Stop()
logger.Flush() logger.Flush()
}) for i := 10; i > 0; i-- {
<-sigc
if i > 1 {
glog.V(logger.Info).Infoln("Already shutting down, please be patient.")
glog.V(logger.Info).Infoln("Interrupt", i-1, "more times to induce panic.")
} }
}
func StartEthereumForTest(ethereum *eth.Ethereum) { glog.V(logger.Error).Infof("Force quitting: this might not end so well.")
glog.V(logger.Info).Infoln("Starting ", ethereum.Name()) panic("boom")
ethereum.StartForTest() }()
RegisterInterrupt(func(sig os.Signal) {
ethereum.Stop()
logger.Flush()
})
} }
func FormatTransactionData(data string) []byte { func FormatTransactionData(data string) []byte {