geth: better error notification
This commit is contained in:
parent
1cc8259589
commit
26841d91e7
|
@ -1101,6 +1101,11 @@ func startTestNode(t *testing.T) <-chan struct{} {
|
|||
t.Errorf("cannot unmarshal event's JSON: %s", jsonEvent)
|
||||
return
|
||||
}
|
||||
if envelope.Type == geth.EventNodeCrashed {
|
||||
geth.TriggerDefaultNodeNotificationHandler(jsonEvent)
|
||||
return
|
||||
}
|
||||
|
||||
if envelope.Type == geth.EventTransactionQueued {
|
||||
}
|
||||
if envelope.Type == geth.EventNodeStarted {
|
||||
|
|
21
geth/node.go
21
geth/node.go
|
@ -9,6 +9,7 @@ import (
|
|||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
|
@ -43,6 +44,7 @@ const (
|
|||
DatabaseCacheSize = 128 // Megabytes of memory allocated to internal caching (min 16MB / database forced)
|
||||
|
||||
EventNodeStarted = "node.started"
|
||||
EventNodeCrashed = "node.crashed"
|
||||
)
|
||||
|
||||
// Gas price settings
|
||||
|
@ -313,5 +315,24 @@ func Fatalf(reason interface{}, args ...interface{}) {
|
|||
fmt.Fprintf(w, "Fatal Failure: %v\n", reason.(error))
|
||||
}
|
||||
|
||||
debug.PrintStack()
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// HaltOnPanic recovers from panic, logs issue, sends upward notification, and exits
|
||||
func HaltOnPanic() {
|
||||
if r := recover(); r != nil {
|
||||
err := fmt.Errorf("%v: %v", ErrNodeStartFailure, r)
|
||||
|
||||
// send signal up to native app
|
||||
SendSignal(SignalEnvelope{
|
||||
Type: EventNodeCrashed,
|
||||
Event: NodeCrashEvent{
|
||||
Error: err.Error(),
|
||||
},
|
||||
})
|
||||
|
||||
Fatalf(err) // os.exit(1) is called internally
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,8 @@ var (
|
|||
|
||||
// CreateAndRunNode creates and starts running Geth node locally (exposing given RPC port along the way)
|
||||
func CreateAndRunNode(dataDir string, rpcPort int) error {
|
||||
defer HaltOnPanic()
|
||||
|
||||
nodeManager := NewNodeManager(dataDir, rpcPort)
|
||||
|
||||
if nodeManager.NodeInited() {
|
||||
|
@ -101,6 +103,8 @@ func NodeManagerInstance() *NodeManager {
|
|||
// RunNode starts Geth node
|
||||
func (m *NodeManager) RunNode() {
|
||||
go func() {
|
||||
defer HaltOnPanic()
|
||||
|
||||
m.StartNode()
|
||||
|
||||
if _, err := m.AccountManager(); err != nil {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package geth_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
@ -37,6 +39,15 @@ func TestMain(m *testing.M) {
|
|||
}
|
||||
|
||||
geth.SetDefaultNodeNotificationHandler(func(jsonEvent string) {
|
||||
var envelope geth.SignalEnvelope
|
||||
if err := json.Unmarshal([]byte(jsonEvent), &envelope); err != nil {
|
||||
panic(fmt.Errorf("cannot unmarshal event's JSON: %s", jsonEvent))
|
||||
}
|
||||
if envelope.Type == geth.EventNodeCrashed {
|
||||
geth.TriggerDefaultNodeNotificationHandler(jsonEvent)
|
||||
return
|
||||
}
|
||||
|
||||
if jsonEvent == `{"type":"node.started","event":{}}` {
|
||||
signalRecieved <- struct{}{}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,10 @@ type JSONError struct {
|
|||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
type NodeCrashEvent struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
type AddPeerResult struct {
|
||||
Success bool `json:"success"`
|
||||
Error string `json:"error"`
|
||||
|
|
|
@ -31,15 +31,19 @@ const (
|
|||
|
||||
type NodeNotificationHandler func(jsonEvent string)
|
||||
|
||||
var notificationHandler NodeNotificationHandler = func(jsonEvent string) { // internal signal handler (used in tests)
|
||||
glog.V(logger.Info).Infof("notification received (default notification handler): %s\n", jsonEvent)
|
||||
}
|
||||
var notificationHandler NodeNotificationHandler = TriggerDefaultNodeNotificationHandler
|
||||
|
||||
// SetDefaultNodeNotificationHandler sets notification handler to invoke on SendSignal
|
||||
func SetDefaultNodeNotificationHandler(fn NodeNotificationHandler) {
|
||||
notificationHandler = fn
|
||||
}
|
||||
|
||||
// SendSignal sends application signal (JSON, normally) upwards
|
||||
// TriggerDefaultNodeNotificationHandler triggers default notification handler (helpful in tests)
|
||||
func TriggerDefaultNodeNotificationHandler(jsonEvent string) {
|
||||
glog.V(logger.Info).Infof("notification received (default notification handler): %s\n", jsonEvent)
|
||||
}
|
||||
|
||||
// SendSignal sends application signal (JSON, normally) upwards to application (via default notification handler)
|
||||
func SendSignal(signal SignalEnvelope) {
|
||||
data, _ := json.Marshal(&signal)
|
||||
C.StatusServiceSignalEvent(C.CString(string(data)))
|
||||
|
@ -98,6 +102,8 @@ func PrepareTestNode() (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
defer HaltOnPanic()
|
||||
|
||||
syncRequired := false
|
||||
if _, err := os.Stat(filepath.Join(TestDataDir, "testnet")); os.IsNotExist(err) {
|
||||
syncRequired = true
|
||||
|
@ -122,7 +128,10 @@ func PrepareTestNode() (err error) {
|
|||
|
||||
// start geth node and wait for it to initialize
|
||||
// internally once.Do() is used, so call below is thread-safe
|
||||
CreateAndRunNode(dataDir, 8546) // to avoid conflicts with running react-native app, run on different port
|
||||
err = CreateAndRunNode(dataDir, 8546) // to avoid conflicts with running react-native app, run on different port
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
manager = NodeManagerInstance()
|
||||
if !manager.NodeInited() {
|
||||
|
|
Loading…
Reference in New Issue