feat: recover from panic
All checks were successful
submodules sync / sync (push) Successful in 1m4s
build / build (push) Successful in 2m21s
build / trigger-build-image (push) Successful in 11s

This commit is contained in:
张泊明518370910136 2025-03-31 05:36:47 -04:00
parent ab41926fc0
commit 4639e84ad5
GPG Key ID: D47306D7062CDA9D
3 changed files with 153 additions and 116 deletions

View File

@ -146,8 +146,18 @@ func mainImpl() (err error) {
}
func main() {
if err := mainImpl(); err != nil {
slog.Error("main exit", "error", err)
os.Exit(1)
}
var err error
exitCode := 0
defer func() {
if r := recover(); r != nil {
slog.Error("panic recovered", "panic", r)
exitCode = 2
}
if err != nil {
slog.Error("main exit", "error", err)
exitCode = 1
}
os.Exit(exitCode)
}()
err = mainImpl()
}

View File

@ -22,7 +22,10 @@ func generateStages(confStages []conf.ConfStage, groups []string) (
) {
stages := []stage.Stage{}
existNames := map[string]bool{}
for _, s := range confStages {
for i, s := range confStages {
if s.Name == "" {
s.Name = fmt.Sprintf("stage-%d", i)
}
if s.Group != "" {
var ok bool
for _, group := range groups {

View File

@ -16,140 +16,164 @@ func Run(stages []Stage) (
var tmpParserResults []ParserResult
slog.Info("stage run start")
for _, stage := range stages {
slog.Info("stage start", "name", stage.Name)
slog.Info(
"executor run start",
"stageName", stage.Name,
"name", stage.Executor.Name,
)
slog.Debug(
"executor run start",
"stageName", stage.Name,
"name", stage.Executor.Name,
"cmds", stage.Executor.Cmds,
)
executor, ok := executorMap[stage.Executor.Name]
if !ok {
slog.Error(
"executor not found",
func() {
defer func() {
if r := recover(); r != nil {
slog.Error(
"stage panic recovered",
"stageName", stage.Name,
"panic", r,
)
stageResults = append(stageResults, StageResult{
Name: stage.Name,
Results: []ParserResult{
{
Score: 0,
Comment: "JOJ3 internal error. " +
"Please contact the administrator.\n",
},
},
ForceQuit: true,
})
forceQuitStageName = stage.Name
err = fmt.Errorf("panic in stage %s: %v", stage.Name, r)
}
}()
slog.Info("stage start", "name", stage.Name)
slog.Info(
"executor run start",
"stageName", stage.Name,
"name", stage.Executor.Name,
)
err = fmt.Errorf("executor not found: %s", stage.Executor.Name)
return stageResults, forceQuitStageName, err
}
executorResults, err = executor.Run(stage.Executor.Cmds)
if err != nil {
slog.Error(
"executor run error",
slog.Debug(
"executor run start",
"stageName", stage.Name,
"name", stage.Executor.Name,
"error", err,
"cmds", stage.Executor.Cmds,
)
return stageResults, forceQuitStageName, err
}
for i, executorResult := range executorResults {
executor, ok := executorMap[stage.Executor.Name]
if !ok {
slog.Error(
"executor not found",
"stageName", stage.Name,
"name", stage.Executor.Name,
)
err = fmt.Errorf("executor not found: %s", stage.Executor.Name)
return
}
executorResults, err = executor.Run(stage.Executor.Cmds)
if err != nil {
slog.Error(
"executor run error",
"stageName", stage.Name,
"name", stage.Executor.Name,
"error", err,
)
return
}
for i, executorResult := range executorResults {
slog.Debug(
"executor run done",
"stageName", stage.Name,
"case", i,
"name", stage.Executor.Name,
"result", executorResult,
)
}
slog.Debug(
"executor run done",
"stageName", stage.Name,
"case", i,
"name", stage.Executor.Name,
"result", executorResult,
"summary", SummarizeExecutorResults(executorResults),
)
}
slog.Debug(
"executor run done",
"stageName", stage.Name,
"name", stage.Executor.Name,
"summary", SummarizeExecutorResults(executorResults),
)
parserResults = []ParserResult{}
stageDetail := StageDetail{
Name: stage.Name,
CaseDetails: make([]CaseDetail, len(executorResults)),
}
parserScoresMap := map[string][]int{}
for _, parser := range stage.Parsers {
parserScoresMap[parser.Name] = make([]int, len(executorResults))
}
for _, stageParser := range stage.Parsers {
slog.Info(
"parser run start",
"stageName", stage.Name,
"name", stageParser.Name,
)
slog.Debug(
"parser run start",
"stageName", stage.Name,
"name", stageParser.Name,
"conf", stageParser.Conf,
)
parser, ok := parserMap[stageParser.Name]
if !ok {
slog.Error(
"parser not found",
parserResults = []ParserResult{}
stageDetail := StageDetail{
Name: stage.Name,
CaseDetails: make([]CaseDetail, len(executorResults)),
}
parserScoresMap := map[string][]int{}
for _, parser := range stage.Parsers {
parserScoresMap[parser.Name] = make([]int, len(executorResults))
}
for _, stageParser := range stage.Parsers {
slog.Info(
"parser run start",
"stageName", stage.Name,
"name", stageParser.Name,
)
err = fmt.Errorf("parser not found: %s", stageParser.Name)
return stageResults, forceQuitStageName, err
}
var parserForceQuit bool
tmpParserResults, parserForceQuit, err = parser.Run(
executorResults, stageParser.Conf)
if err != nil {
slog.Error(
"parser run error",
slog.Debug(
"parser run start",
"stageName", stage.Name,
"name", stageParser.Name,
"error", err,
"conf", stageParser.Conf,
)
forceQuitStageName = stage.Name
break
}
for i, parserResult := range tmpParserResults {
parserScoresMap[stageParser.Name][i] += parserResult.Score
}
if parserForceQuit {
slog.Error(
"parser force quit",
parser, ok := parserMap[stageParser.Name]
if !ok {
slog.Error(
"parser not found",
"stageName", stage.Name,
"name", stageParser.Name,
)
err = fmt.Errorf("parser not found: %s", stageParser.Name)
return
}
var parserForceQuit bool
tmpParserResults, parserForceQuit, err = parser.Run(
executorResults, stageParser.Conf)
if err != nil {
slog.Error(
"parser run error",
"stageName", stage.Name,
"name", stageParser.Name,
"error", err,
)
forceQuitStageName = stage.Name
break
}
for i, parserResult := range tmpParserResults {
parserScoresMap[stageParser.Name][i] += parserResult.Score
}
if parserForceQuit {
slog.Error(
"parser force quit",
"stageName", stage.Name,
"name", stageParser.Name,
)
forceQuitStageName = stage.Name
}
slog.Debug(
"parser run done",
"stageName", stage.Name,
"name", stageParser.Name,
"results", tmpParserResults,
)
forceQuitStageName = stage.Name
}
slog.Debug(
"parser run done",
"stageName", stage.Name,
"name", stageParser.Name,
"results", tmpParserResults,
)
if len(parserResults) == 0 {
parserResults = tmpParserResults
} else {
for i := range len(parserResults) {
parserResults[i].Score += tmpParserResults[i].Score
parserResults[i].Comment += tmpParserResults[i].Comment
if len(parserResults) == 0 {
parserResults = tmpParserResults
} else {
for i := range len(parserResults) {
parserResults[i].Score += tmpParserResults[i].Score
parserResults[i].Comment += tmpParserResults[i].Comment
}
}
}
}
for i := range executorResults {
caseDetail := CaseDetail{
Index: i,
ExecutorResult: executorResults[i],
ParserScores: make(map[string]int),
for i := range executorResults {
caseDetail := CaseDetail{
Index: i,
ExecutorResult: executorResults[i],
ParserScores: make(map[string]int),
}
for name, scores := range parserScoresMap {
caseDetail.ParserScores[name] = scores[i]
}
stageDetail.CaseDetails[i] = caseDetail
}
for name, scores := range parserScoresMap {
caseDetail.ParserScores[name] = scores[i]
}
stageDetail.CaseDetails[i] = caseDetail
}
stageResults = append(stageResults, StageResult{
Name: stage.Name,
Results: parserResults,
ForceQuit: forceQuitStageName != "",
})
slog.Debug("stage done", "name", stage.Name, "stageDetail", stageDetail)
stageResults = append(stageResults, StageResult{
Name: stage.Name,
Results: parserResults,
ForceQuit: forceQuitStageName != "",
})
slog.Debug("stage done", "name", stage.Name, "stageDetail", stageDetail)
}()
if forceQuitStageName != "" {
break
}