Merge pull request #374 from guggero/db-timeout

loopd+loopdb: add timeout to DB open
pull/375/head
Oliver Gugger 3 years ago committed by GitHub
commit 9fe7ab1a0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -11,6 +11,7 @@ import (
"sync"
"sync/atomic"
"github.com/coreos/bbolt"
proxy "github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/lightninglabs/lndclient"
"github.com/lightninglabs/loop"
@ -128,6 +129,13 @@ func (d *Daemon) Start() error {
// and error handlers. If this fails, then nothing has been started yet
// and we can just return the error.
err = d.initialize()
if errors.Is(err, bbolt.ErrTimeout) {
// We're trying to be started as a standalone Loop daemon, most
// likely LiT is already running and blocking the DB
return fmt.Errorf("%v: make sure no other loop daemon "+
"process (standalone or embedded in "+
"lightning-terminal) is running", err)
}
if err != nil {
return err
}
@ -168,7 +176,14 @@ func (d *Daemon) StartAsSubserver(lndGrpc *lndclient.GrpcLndServices) error {
// the swap server client, the RPC server instance and our main swap
// handlers. If this fails, then nothing has been started yet and we can
// just return the error.
return d.initialize()
err := d.initialize()
if errors.Is(err, bbolt.ErrTimeout) {
// We're trying to be started inside LiT so there most likely is
// another standalone Loop process blocking the DB.
return fmt.Errorf("%v: make sure no other loop daemon "+
"process is running", err)
}
return err
}
// ValidateMacaroon extracts the macaroon from the context's gRPC metadata,

@ -5,8 +5,9 @@ import (
"fmt"
"io/ioutil"
"os"
"time"
"github.com/coreos/bbolt"
"github.com/lightninglabs/loop/loopdb"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/macaroons"
"google.golang.org/grpc"
@ -17,10 +18,6 @@ const (
// loopMacaroonLocation is the value we use for the loopd macaroons'
// "Location" field when baking them.
loopMacaroonLocation = "loop"
// macDatabaseOpenTimeout is how long we wait for acquiring the lock on
// the macaroon database before we give up with an error.
macDatabaseOpenTimeout = time.Second * 5
)
var (
@ -150,8 +147,14 @@ func (d *Daemon) startMacaroonService() error {
var err error
d.macaroonService, err = macaroons.NewService(
d.cfg.DataDir, loopMacaroonLocation, false,
macDatabaseOpenTimeout, macaroons.IPLockChecker,
loopdb.DefaultLoopDBTimeout, macaroons.IPLockChecker,
)
if err == bbolt.ErrTimeout {
return fmt.Errorf("%w: couldn't obtain exclusive lock on "+
"%s/%s, timed out after %v", bbolt.ErrTimeout,
d.cfg.DataDir, "macaroons.db",
loopdb.DefaultLoopDBTimeout)
}
if err != nil {
return fmt.Errorf("unable to set up macaroon authentication: "+
"%v", err)

@ -99,9 +99,18 @@ var (
keyLength = 33
)
// DefaultLoopOutHtlcConfirmations is the default number of confirmations we
// set for a loop out htlc.
const DefaultLoopOutHtlcConfirmations uint32 = 1
const (
// DefaultLoopOutHtlcConfirmations is the default number of
// confirmations we set for a loop out htlc.
DefaultLoopOutHtlcConfirmations uint32 = 1
// DefaultLoopDBTimeout is the default maximum time we wait for the
// Loop bbolt database to be opened. If the database is already opened
// by another process, the unique lock cannot be obtained. With the
// timeout we error out after the given time instead of just blocking
// for forever.
DefaultLoopDBTimeout = 5 * time.Second
)
// fileExists returns true if the file exists, and false otherwise.
func fileExists(path string) bool {
@ -139,7 +148,14 @@ func NewBoltSwapStore(dbPath string, chainParams *chaincfg.Params) (
// Now that we know that path exists, we'll open up bolt, which
// implements our default swap store.
path := filepath.Join(dbPath, dbFileName)
bdb, err := bbolt.Open(path, 0600, nil)
bdb, err := bbolt.Open(path, 0600, &bbolt.Options{
Timeout: DefaultLoopDBTimeout,
})
if err == bbolt.ErrTimeout {
return nil, fmt.Errorf("%w: couldn't obtain exclusive lock on "+
"%s, timed out after %v", bbolt.ErrTimeout, path,
DefaultLoopDBTimeout)
}
if err != nil {
return nil, err
}

@ -19,3 +19,6 @@ This file tracks release notes for the loop client.
#### Breaking Changes
#### Bug Fixes
- Instead of just blocking for forever without any apparent reason if another
Loop daemon process is already running, we now exit with an error after 5
seconds if acquiring the unique lock on the Loop `bbolt` DB fails.

Loading…
Cancel
Save