diff --git a/error.go b/error.go deleted file mode 100644 index 25c3cae..0000000 --- a/error.go +++ /dev/null @@ -1,46 +0,0 @@ -package main - -import ( - "errors" - "log" - - "git.gensokyo.uk/security/fortify/internal/app" - "git.gensokyo.uk/security/fortify/internal/fmsg" -) - -func logWaitError(err error) { - var e *fmsg.BaseError - if !fmsg.AsBaseError(err, &e) { - log.Println("wait failed:", err) - } else { - // Wait only returns either *app.ProcessError or *app.StateStoreError wrapped in a *app.BaseError - var se *app.StateStoreError - if !errors.As(err, &se) { - // does not need special handling - log.Print(e.Message()) - } else { - // inner error are either unwrapped store errors - // or joined errors returned by *appSealTx revert - // wrapped in *app.BaseError - var ej app.RevertCompoundError - if !errors.As(se.InnerErr, &ej) { - // does not require special handling - log.Print(e.Message()) - } else { - errs := ej.Unwrap() - - // every error here is wrapped in *app.BaseError - for _, ei := range errs { - var eb *fmsg.BaseError - if !errors.As(ei, &eb) { - // unreachable - log.Println("invalid error type returned by revert:", ei) - } else { - // print inner *app.BaseError message - log.Print(eb.Message()) - } - } - } - } - } -} diff --git a/internal/app/errors.go b/internal/app/errors.go index c5209c4..6b5cffe 100644 --- a/internal/app/errors.go +++ b/internal/app/errors.go @@ -2,10 +2,110 @@ package app import ( "errors" + "log" + "git.gensokyo.uk/security/fortify/fst" "git.gensokyo.uk/security/fortify/internal/fmsg" ) +func PrintRunStateErr(rs *fst.RunState, runErr error) { + if runErr != nil { + if rs.Time == nil { + fmsg.PrintBaseError(runErr, "cannot start app:") + } else { + var e *fmsg.BaseError + if !fmsg.AsBaseError(runErr, &e) { + log.Println("wait failed:", runErr) + } else { + // Wait only returns either *app.ProcessError or *app.StateStoreError wrapped in a *app.BaseError + var se *StateStoreError + if !errors.As(runErr, &se) { + // does not need special handling + log.Print(e.Message()) + } else { + // inner error are either unwrapped store errors + // or joined errors returned by *appSealTx revert + // wrapped in *app.BaseError + var ej RevertCompoundError + if !errors.As(se.InnerErr, &ej) { + // does not require special handling + log.Print(e.Message()) + } else { + errs := ej.Unwrap() + + // every error here is wrapped in *app.BaseError + for _, ei := range errs { + var eb *fmsg.BaseError + if !errors.As(ei, &eb) { + // unreachable + log.Println("invalid error type returned by revert:", ei) + } else { + // print inner *app.BaseError message + log.Print(eb.Message()) + } + } + } + } + } + } + + if rs.ExitCode == 0 { + rs.ExitCode = 126 + } + } + + if rs.RevertErr != nil { + var stateStoreError *StateStoreError + if !errors.As(rs.RevertErr, &stateStoreError) || stateStoreError == nil { + fmsg.PrintBaseError(rs.RevertErr, "generic fault during cleanup:") + goto out + } + + if stateStoreError.Err != nil { + if len(stateStoreError.Err) == 2 { + if stateStoreError.Err[0] != nil { + if joinedErrs, ok := stateStoreError.Err[0].(interface{ Unwrap() []error }); !ok { + fmsg.PrintBaseError(stateStoreError.Err[0], "generic fault during revert:") + } else { + for _, err := range joinedErrs.Unwrap() { + if err != nil { + fmsg.PrintBaseError(err, "fault during revert:") + } + } + } + } + if stateStoreError.Err[1] != nil { + log.Printf("cannot close store: %v", stateStoreError.Err[1]) + } + } else { + log.Printf("fault during cleanup: %v", + errors.Join(stateStoreError.Err...)) + } + } + + if stateStoreError.OpErr != nil { + log.Printf("blind revert due to store fault: %v", + stateStoreError.OpErr) + } + + if stateStoreError.DoErr != nil { + fmsg.PrintBaseError(stateStoreError.DoErr, "state store operation unsuccessful:") + } + + if stateStoreError.Inner && stateStoreError.InnerErr != nil { + fmsg.PrintBaseError(stateStoreError.InnerErr, "cannot destroy state entry:") + } + + out: + if rs.ExitCode == 0 { + rs.ExitCode = 128 + } + } + if rs.WaitErr != nil { + log.Println("inner wait failed:", rs.WaitErr) + } +} + // StateStoreError is returned for a failed state save type StateStoreError struct { // whether inner function was called diff --git a/main.go b/main.go index 8df2659..3d3e479 100644 --- a/main.go +++ b/main.go @@ -286,74 +286,17 @@ func buildCommand(out io.Writer) command.Command { } func runApp(a fst.App, config *fst.Config) { - rs := new(fst.RunState) ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() // unreachable + rs := new(fst.RunState) if sa, err := a.Seal(config); err != nil { fmsg.PrintBaseError(err, "cannot seal app:") - internal.Exit(1) - } else if err = sa.Run(ctx, rs); err != nil { - if rs.Time == nil { - fmsg.PrintBaseError(err, "cannot start app:") - } else { - logWaitError(err) - } - - if rs.ExitCode == 0 { - rs.ExitCode = 126 - } - } - if rs.RevertErr != nil { - var stateStoreError *app.StateStoreError - if !errors.As(rs.RevertErr, &stateStoreError) || stateStoreError == nil { - fmsg.PrintBaseError(rs.RevertErr, "generic fault during cleanup:") - goto out - } - - if stateStoreError.Err != nil { - if len(stateStoreError.Err) == 2 { - if stateStoreError.Err[0] != nil { - if joinedErrs, ok := stateStoreError.Err[0].(interface{ Unwrap() []error }); !ok { - fmsg.PrintBaseError(stateStoreError.Err[0], "generic fault during revert:") - } else { - for _, err := range joinedErrs.Unwrap() { - if err != nil { - fmsg.PrintBaseError(err, "fault during revert:") - } - } - } - } - if stateStoreError.Err[1] != nil { - log.Printf("cannot close store: %v", stateStoreError.Err[1]) - } - } else { - log.Printf("fault during cleanup: %v", - errors.Join(stateStoreError.Err...)) - } - } - - if stateStoreError.OpErr != nil { - log.Printf("blind revert due to store fault: %v", - stateStoreError.OpErr) - } - - if stateStoreError.DoErr != nil { - fmsg.PrintBaseError(stateStoreError.DoErr, "state store operation unsuccessful:") - } - - if stateStoreError.Inner && stateStoreError.InnerErr != nil { - fmsg.PrintBaseError(stateStoreError.InnerErr, "cannot destroy state entry:") - } - - out: - if rs.ExitCode == 0 { - rs.ExitCode = 128 - } - } - if rs.WaitErr != nil { - log.Println("inner wait failed:", rs.WaitErr) + rs.ExitCode = 1 + } else { + // this updates ExitCode + app.PrintRunStateErr(rs, sa.Run(ctx, rs)) } internal.Exit(rs.ExitCode) }