Skip to content

Commit

Permalink
Merge pull request ethereum#15000 from fjl/node-flock
Browse files Browse the repository at this point in the history
node: fix instance dir locking and improve error message
  • Loading branch information
karalabe authored Aug 23, 2017
2 parents 79cdbcf + 7e57fee commit f7e39a7
Show file tree
Hide file tree
Showing 10 changed files with 551 additions and 24 deletions.
18 changes: 18 additions & 0 deletions node/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,28 @@
package node

import (
"errors"
"fmt"
"reflect"
"syscall"
)

var (
ErrDatadirUsed = errors.New("datadir already used by another process")
ErrNodeStopped = errors.New("node not started")
ErrNodeRunning = errors.New("node already running")
ErrServiceUnknown = errors.New("unknown service")

datadirInUseErrnos = map[uint]bool{11: true, 32: true, 35: true}
)

func convertFileLockError(err error) error {
if errno, ok := err.(syscall.Errno); ok && datadirInUseErrnos[uint(errno)] {
return ErrDatadirUsed
}
return err
}

// DuplicateServiceError is returned during Node startup if a registered service
// constructor returns a service of the same type that was already started.
type DuplicateServiceError struct {
Expand Down
36 changes: 12 additions & 24 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"reflect"
"strings"
"sync"
"syscall"

"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/ethdb"
Expand All @@ -34,16 +33,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rpc"
"github.com/syndtr/goleveldb/leveldb/storage"
)

var (
ErrDatadirUsed = errors.New("datadir already used")
ErrNodeStopped = errors.New("node not started")
ErrNodeRunning = errors.New("node already running")
ErrServiceUnknown = errors.New("unknown service")

datadirInUseErrnos = map[uint]bool{11: true, 32: true, 35: true}
"github.com/prometheus/prometheus/util/flock"
)

// Node is a container on which services can be registered.
Expand All @@ -52,8 +42,8 @@ type Node struct {
config *Config
accman *accounts.Manager

ephemeralKeystore string // if non-empty, the key directory that will be removed by Stop
instanceDirLock storage.Storage // prevents concurrent use of instance directory
ephemeralKeystore string // if non-empty, the key directory that will be removed by Stop
instanceDirLock flock.Releaser // prevents concurrent use of instance directory

serverConfig p2p.Config
server *p2p.Server // Currently running P2P networking layer
Expand Down Expand Up @@ -197,10 +187,7 @@ func (n *Node) Start() error {
running.Protocols = append(running.Protocols, service.Protocols()...)
}
if err := running.Start(); err != nil {
if errno, ok := err.(syscall.Errno); ok && datadirInUseErrnos[uint(errno)] {
return ErrDatadirUsed
}
return err
return convertFileLockError(err)
}
// Start each of the services
started := []reflect.Type{}
Expand Down Expand Up @@ -242,14 +229,13 @@ func (n *Node) openDataDir() error {
if err := os.MkdirAll(instdir, 0700); err != nil {
return err
}
// Try to open the instance directory as LevelDB storage. This creates a lock file
// which prevents concurrent use by another instance as well as accidental use of the
// instance directory as a database.
storage, err := storage.OpenFile(instdir, true)
// Lock the instance directory to prevent concurrent use by another instance as well as
// accidental use of the instance directory as a database.
release, _, err := flock.New(filepath.Join(instdir, "LOCK"))
if err != nil {
return err
return convertFileLockError(err)
}
n.instanceDirLock = storage
n.instanceDirLock = release
return nil
}

Expand Down Expand Up @@ -509,7 +495,9 @@ func (n *Node) Stop() error {

// Release instance directory lock.
if n.instanceDirLock != nil {
n.instanceDirLock.Close()
if err := n.instanceDirLock.Release(); err != nil {
log.Error("Can't release datadir lock", "err", err)
}
n.instanceDirLock = nil
}

Expand Down
201 changes: 201 additions & 0 deletions vendor/github.com/prometheus/prometheus/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

87 changes: 87 additions & 0 deletions vendor/github.com/prometheus/prometheus/NOTICE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit f7e39a7

Please sign in to comment.