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
67
cmd.go
67
cmd.go
|
@ -102,37 +102,24 @@ func accessClient() (*rpcClient, error) {
|
|||
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() {
|
||||
// Work around defer not working after os.Exit.
|
||||
if err := walletMain(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 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
|
||||
// initializes logging and configures it accordingly.
|
||||
tcfg, _, err := loadConfig()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
return err
|
||||
}
|
||||
cfg = tcfg
|
||||
defer backendLog.Flush()
|
||||
|
@ -152,11 +139,14 @@ func main() {
|
|||
certs, err := ioutil.ReadFile(cfg.CAFile)
|
||||
if err != nil {
|
||||
log.Errorf("cannot open CA file: %v", err)
|
||||
os.Exit(1)
|
||||
return err
|
||||
}
|
||||
|
||||
// Check and update any old file locations.
|
||||
updateOldFileLocations()
|
||||
err = updateOldFileLocations()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Start account manager and open accounts.
|
||||
AcctMgr.Start()
|
||||
|
@ -164,7 +154,7 @@ func main() {
|
|||
server, err = newRPCServer(cfg.SvrListeners)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to create HTTP server: %v", err)
|
||||
os.Exit(1)
|
||||
return err
|
||||
}
|
||||
|
||||
// Start HTTP server to serve wallet client connections.
|
||||
|
@ -174,5 +164,26 @@ func main() {
|
|||
// reconnections if the client could not be successfully connected.
|
||||
clientChan := make(chan *rpcClient)
|
||||
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
|
||||
// recorded unspent transaction outputs to more recent locations.
|
||||
//
|
||||
// If any errors are encounted during this function, the application is
|
||||
// closed.
|
||||
func updateOldFileLocations() {
|
||||
func updateOldFileLocations() error {
|
||||
// Before version 0.1.1, accounts were saved with the following
|
||||
// format:
|
||||
//
|
||||
|
@ -69,7 +66,7 @@ func updateOldFileLocations() {
|
|||
|
||||
datafi, err := os.Open(cfg.DataDir)
|
||||
if err != nil {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
defer func() {
|
||||
if err := datafi.Close(); err != nil {
|
||||
|
@ -81,7 +78,7 @@ func updateOldFileLocations() {
|
|||
fi, err := datafi.Readdir(0)
|
||||
if err != nil {
|
||||
log.Errorf("Cannot read files in data directory: %v", err)
|
||||
os.Exit(1)
|
||||
return err
|
||||
}
|
||||
|
||||
acctsExist := false
|
||||
|
@ -97,14 +94,14 @@ func updateOldFileLocations() {
|
|||
}
|
||||
}
|
||||
if !acctsExist {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create testnet directory, if it doesn't already exist.
|
||||
netdir := filepath.Join(cfg.DataDir, "testnet")
|
||||
if err := checkCreateDir(netdir); err != nil {
|
||||
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.
|
||||
|
@ -124,7 +121,7 @@ func updateOldFileLocations() {
|
|||
|
||||
default: // all other non-nil errors
|
||||
log.Errorf("Cannot open old account directory: %v", err)
|
||||
os.Exit(1)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Updating old file locations for account %v", account)
|
||||
|
@ -136,7 +133,7 @@ func updateOldFileLocations() {
|
|||
if err := Rename(old, new); err != nil {
|
||||
log.Errorf("Cannot move old %v for account %v to new location: %v",
|
||||
"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)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type oldAccountDir struct {
|
||||
|
|
Loading…
Reference in a new issue