package argvpb import ( "fmt" "os" "time" "go.wit.com/lib/cobol" ) // since we know when the command starts (duh, this parses os.Args) // this is a convienent way to provide a standard exit format back // to the shell that also has built in timing! // also, it supports a custom Exit() back to your application func GoodExit(msg string) { me.pb.GoodExit(msg) } func BadExit(msg string, err error) { me.pb.BadExit(msg, err) } func (pb *Argv) GoodExit(msg string) { go ExitWatchdog() if me.appExit != nil { me.appExit() } dur := time.Since(pb.Ctime.AsTime()) var appname string if pb.AppInfo == nil { appname = os.Args[0] } else { appname = pb.AppInfo.APPNAME } fmt.Printf("%s: %s (%s)\n", appname, msg, cobol.FormatDuration(dur)) os.Exit(0) } func (pb *Argv) BadExit(msg string, err error) { go ExitWatchdog() if me.appExit != nil { me.appExit() } // print out errors. this handles wrapped errors which is a useful if err != nil { if u, ok := err.(interface{ Unwrap() []error }); ok { // If it does, call the method to get the slice of errors. allerr := u.Unwrap() for _, e := range allerr { fmt.Printf("Error: (%v)\n", e) } } else { // If it's not a joined error, you can fall back to the single-unwrap loop. fmt.Printf("Error: (%v)\n", u) } } dur := time.Since(pb.Ctime.AsTime()) var appname string if pb.AppInfo == nil { appname = os.Args[0] } else { appname = pb.AppInfo.APPNAME } fmt.Printf("%s error: %s (%s)\n", appname, msg, cobol.FormatDuration(dur)) os.Exit(1) } // this code doesn't need to be this complicated. I put it here as reference code for myself so I could remember where it is. func ExitWatchdog() { dog := time.NewTicker(5 * time.Second) defer dog.Stop() dogchan := make(chan bool) /* // this example would exit/destroy the ticker in 10 seconds go func() { time.Sleep(10 * time.Second) done <- true }() */ for { select { case <-dogchan: fmt.Println("Done!") return case t := <-dog.C: _ = t fmt.Println("argv.Exit() watchdog: stalled in", me.pb.AppInfo.APPNAME+".Exit()") // h.Scan() } } }