robfig / cron

a cron library for go
MIT License
13.15k stars 1.63k forks source link

cannot recovery from panic when in gin server program,what's wrong with my code? #489

Closed ccpwcn closed 1 year ago

ccpwcn commented 1 year ago

This is my code:

package main

import (
    "time"

    "github.com/robfig/cron/v3"
    "go.uber.org/zap"
)

var (
    c         *cron.Cron
    logger, _ = zap.NewProduction()
)

func Log() *zap.Logger {
    return logger
}

type SchedulerTask struct {
    Name     string
    Cron     string
    FuncName string
    FuncArgs []string
}

func (task SchedulerTask) Run() {
    Log().Info("调度任务常规信息", zap.String("task", task.Name))
    Log().Debug("调度任务调试信息", zap.String("task", task.Name))
    Log().Error("调度任务示例错误信息", zap.String("task", task.Name))
    Log().Warn("调度任务示例警告信息", zap.String("task", task.Name))
    panic("调度任务示例恐慌信息")
}

type CronLogger struct{}

func (cl CronLogger) Info(msg string, keysAndValues ...interface{}) {
    Log().Info("任务调度器INFO日志", zap.String("msg", msg), zap.Any("keysAndValues", keysAndValues))
}

func (cl CronLogger) Error(err error, msg string, keysAndValues ...interface{}) {
    Log().Error("任务调度器ERROR日志", zap.String("msg", msg), zap.Error(err), zap.Any("keysAndValues", keysAndValues))
}

func main() {
    cl := CronLogger{}
    c = cron.New(cron.WithLogger(cl), cron.WithChain(cron.SkipIfStillRunning(cl), cron.Recover(cl)))
    st := SchedulerTask{
        Name:     "task1",
        Cron:     "0/1 * * * *",
        FuncName: "demo1",
        FuncArgs: nil,
    }
    c.AddJob(st.Cron, st)
    c.Start()

    time.Sleep(3 * time.Minute)
    return
}

this code runs ok, but, when I put it in gin server program, look like this:

package service

import (
    "time"

    "github.com/robfig/cron/v3"
    "go.uber.org/zap"
)

var (
    c         *cron.Cron
    logger, _ = zap.NewProduction()
)

func Log() *zap.Logger {
    return logger
}

type SchedulerTask struct {
    Name     string
    Cron     string
    FuncName string
    FuncArgs []string
}

func (task SchedulerTask) Run() {
    Log().Info("调度任务常规信息", zap.String("task", task.Name))
    Log().Debug("调度任务调试信息", zap.String("task", task.Name))
    Log().Error("调度任务示例错误信息", zap.String("task", task.Name))
    Log().Warn("调度任务示例警告信息", zap.String("task", task.Name))
    panic("调度任务示例恐慌信息")
}

type CronLogger struct{}

func (cl CronLogger) Info(msg string, keysAndValues ...interface{}) {
    Log().Info("任务调度器INFO日志", zap.String("msg", msg), zap.Any("keysAndValues", keysAndValues))
}

func (cl CronLogger) Error(err error, msg string, keysAndValues ...interface{}) {
    Log().Error("任务调度器ERROR日志", zap.String("msg", msg), zap.Error(err), zap.Any("keysAndValues", keysAndValues))
}

func InitCron() {
    cl := CronLogger{}
    c = cron.New(cron.WithLogger(cl), cron.WithChain(cron.SkipIfStillRunning(cl), cron.Recover(cl)))
    st := SchedulerTask{
        Name:     "task1",
        Cron:     "0/1 * * * *",
        FuncName: "demo1",
        FuncArgs: nil,
    }
    c.AddJob(st.Cron, st)
    c.Start()
}

in main.go, I call InitCron(), then start gin server, look like this:

package main
import (
    "github.com/gin-gonic/gin"
    "service"
)

func main() {
        service.InitCron()

    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run() // 监听并在 0.0.0.0:8080 上启动服务
}

When panic occurs in SchedulerTask.Run(), the entire program exits, That means cron.Recover(cl) won't work.. What is the reason for this?

ccpwcn commented 1 year ago

I tried it a few more times and found a strange thing. If I had a bunch of cron initialization and call related code with the main package and executed it first to start gin, it would be fine, but if I put it in another package, started it and then went back to the main package to start gin, it wouldn't work. panic causes the program to exit. It's really weird.

又试了很多次,发现一个奇怪的现象,如果我的那一堆cron初始化及调用相关的代码,和main包在一起,先执行它们再去启动gin服务,是没问题,如果放在另外的一个代码包中,启动它之后回到main包中启动gin服务器,竟然就不行了,会导致panic引发程序退出。真的是太奇怪了。

ccpwcn commented 1 year ago

排查了一段时间,不是robig/cron的问题,是我的问题,忽略这个吧。