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:
Josh Rickmar 2014-06-21 10:39:27 -05:00
parent cf92f1e5df
commit 0439cdfab5
2 changed files with 48 additions and 38 deletions

67
cmd.go
View file

@ -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()
}
}

View file

@ -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 {