Flush logs and run other defers before os.Exit.
As calls os.Exit do not run deferred functions (such as log flushing), the real main function should simply run a main helper function that, rather than exiting the program, runs all defers and returns a possibly non-nil error. The real main function can then check the error and close the program with an error exit status when a fatal error occured.
This commit is contained in:
parent
cf92f1e5df
commit
0439cdfab5
2 changed files with 48 additions and 38 deletions
71
cmd.go
71
cmd.go
|
@ -102,37 +102,24 @@ func accessClient() (*rpcClient, error) {
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func clientConnect(certs []byte, newClient chan<- *rpcClient) {
|
|
||||||
const initialWait = 5 * time.Second
|
|
||||||
wait := initialWait
|
|
||||||
for {
|
|
||||||
client, err := newRPCClient(certs)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("Unable to open chain server client "+
|
|
||||||
"connection: %v", err)
|
|
||||||
time.Sleep(wait)
|
|
||||||
wait <<= 1
|
|
||||||
if wait > time.Minute {
|
|
||||||
wait = time.Minute
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
wait = initialWait
|
|
||||||
|
|
||||||
client.Start()
|
|
||||||
newClient <- client
|
|
||||||
|
|
||||||
client.WaitForShutdown()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// Work around defer not working after os.Exit.
|
||||||
|
if err := walletMain(); err != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// walletMain is a work-around main function that is required since deferred
|
||||||
|
// functions (such as log flushing) are not called with calls to os.Exit.
|
||||||
|
// Instead, main runs this function and checks for a non-nil error, at which
|
||||||
|
// point any defers have already run, and if the error is non-nil, the program
|
||||||
|
// can be exited with an error exit status.
|
||||||
|
func walletMain() error {
|
||||||
// Load configuration and parse command line. This function also
|
// Load configuration and parse command line. This function also
|
||||||
// initializes logging and configures it accordingly.
|
// initializes logging and configures it accordingly.
|
||||||
tcfg, _, err := loadConfig()
|
tcfg, _, err := loadConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Exit(1)
|
return err
|
||||||
}
|
}
|
||||||
cfg = tcfg
|
cfg = tcfg
|
||||||
defer backendLog.Flush()
|
defer backendLog.Flush()
|
||||||
|
@ -152,11 +139,14 @@ func main() {
|
||||||
certs, err := ioutil.ReadFile(cfg.CAFile)
|
certs, err := ioutil.ReadFile(cfg.CAFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("cannot open CA file: %v", err)
|
log.Errorf("cannot open CA file: %v", err)
|
||||||
os.Exit(1)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check and update any old file locations.
|
// Check and update any old file locations.
|
||||||
updateOldFileLocations()
|
err = updateOldFileLocations()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Start account manager and open accounts.
|
// Start account manager and open accounts.
|
||||||
AcctMgr.Start()
|
AcctMgr.Start()
|
||||||
|
@ -164,7 +154,7 @@ func main() {
|
||||||
server, err = newRPCServer(cfg.SvrListeners)
|
server, err = newRPCServer(cfg.SvrListeners)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Unable to create HTTP server: %v", err)
|
log.Errorf("Unable to create HTTP server: %v", err)
|
||||||
os.Exit(1)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start HTTP server to serve wallet client connections.
|
// Start HTTP server to serve wallet client connections.
|
||||||
|
@ -174,5 +164,26 @@ func main() {
|
||||||
// reconnections if the client could not be successfully connected.
|
// reconnections if the client could not be successfully connected.
|
||||||
clientChan := make(chan *rpcClient)
|
clientChan := make(chan *rpcClient)
|
||||||
go clientAccess(clientChan)
|
go clientAccess(clientChan)
|
||||||
clientConnect(certs, clientChan)
|
const initialWait = 5 * time.Second
|
||||||
|
wait := initialWait
|
||||||
|
for {
|
||||||
|
client, err := newRPCClient(certs)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Unable to open chain server client "+
|
||||||
|
"connection: %v", err)
|
||||||
|
time.Sleep(wait)
|
||||||
|
wait <<= 1
|
||||||
|
if wait > time.Minute {
|
||||||
|
wait = time.Minute
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
wait = initialWait
|
||||||
|
|
||||||
|
client.Start()
|
||||||
|
clientChan <- client
|
||||||
|
|
||||||
|
client.WaitForShutdown()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
19
updates.go
19
updates.go
|
@ -29,10 +29,7 @@ var ErrNotAccountDir = errors.New("directory is not an account directory")
|
||||||
|
|
||||||
// updateOldFileLocations moves files for wallets, transactions, and
|
// updateOldFileLocations moves files for wallets, transactions, and
|
||||||
// recorded unspent transaction outputs to more recent locations.
|
// recorded unspent transaction outputs to more recent locations.
|
||||||
//
|
func updateOldFileLocations() error {
|
||||||
// If any errors are encounted during this function, the application is
|
|
||||||
// closed.
|
|
||||||
func updateOldFileLocations() {
|
|
||||||
// Before version 0.1.1, accounts were saved with the following
|
// Before version 0.1.1, accounts were saved with the following
|
||||||
// format:
|
// format:
|
||||||
//
|
//
|
||||||
|
@ -69,7 +66,7 @@ func updateOldFileLocations() {
|
||||||
|
|
||||||
datafi, err := os.Open(cfg.DataDir)
|
datafi, err := os.Open(cfg.DataDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := datafi.Close(); err != nil {
|
if err := datafi.Close(); err != nil {
|
||||||
|
@ -81,7 +78,7 @@ func updateOldFileLocations() {
|
||||||
fi, err := datafi.Readdir(0)
|
fi, err := datafi.Readdir(0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Cannot read files in data directory: %v", err)
|
log.Errorf("Cannot read files in data directory: %v", err)
|
||||||
os.Exit(1)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
acctsExist := false
|
acctsExist := false
|
||||||
|
@ -97,14 +94,14 @@ func updateOldFileLocations() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !acctsExist {
|
if !acctsExist {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create testnet directory, if it doesn't already exist.
|
// Create testnet directory, if it doesn't already exist.
|
||||||
netdir := filepath.Join(cfg.DataDir, "testnet")
|
netdir := filepath.Join(cfg.DataDir, "testnet")
|
||||||
if err := checkCreateDir(netdir); err != nil {
|
if err := checkCreateDir(netdir); err != nil {
|
||||||
log.Errorf("Cannot continue without a testnet directory: %v", err)
|
log.Errorf("Cannot continue without a testnet directory: %v", err)
|
||||||
os.Exit(1)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check all files in the datadir for old accounts to update.
|
// Check all files in the datadir for old accounts to update.
|
||||||
|
@ -124,7 +121,7 @@ func updateOldFileLocations() {
|
||||||
|
|
||||||
default: // all other non-nil errors
|
default: // all other non-nil errors
|
||||||
log.Errorf("Cannot open old account directory: %v", err)
|
log.Errorf("Cannot open old account directory: %v", err)
|
||||||
os.Exit(1)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Updating old file locations for account %v", account)
|
log.Infof("Updating old file locations for account %v", account)
|
||||||
|
@ -136,7 +133,7 @@ func updateOldFileLocations() {
|
||||||
if err := Rename(old, new); err != nil {
|
if err := Rename(old, new); err != nil {
|
||||||
log.Errorf("Cannot move old %v for account %v to new location: %v",
|
log.Errorf("Cannot move old %v for account %v to new location: %v",
|
||||||
"wallet.bin", account, err)
|
"wallet.bin", account, err)
|
||||||
os.Exit(1)
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,6 +142,8 @@ func updateOldFileLocations() {
|
||||||
log.Warnf("Could not remove pre 0.1.1 account directory: %v", err)
|
log.Warnf("Could not remove pre 0.1.1 account directory: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type oldAccountDir struct {
|
type oldAccountDir struct {
|
||||||
|
|
Loading…
Reference in a new issue