package svc import ( commonConfig "cicv-data-closedloop/pji/common/cfg" "cicv-data-closedloop/pji/common/log" "cicv-data-closedloop/pji/common/util" "net/rpc" "os" "sync" "time" ) var ( ChannelKillRosRecord = make(chan int) ChannelKillDiskClean = make(chan int) ChannelKillSubscriber = make(chan int) ChannelKillMove = make(chan int) ChannelKillConsume = make(chan int) KillChannel = 5 KillTimes = 0 MutexKill sync.Mutex ) // KillSignal 停止信号,主从节点接收到数据后准备重启 type KillSignal struct { NodeName string DropUploadData bool Restart bool } // KillService 定义要远程调用的类型和方法 type KillService struct{} // Kill 杀死自身程序,通过通道实现 方法必须满足RPC规范:函数有两个参数,第一个参数是请求,第二个是响应 func (m *KillService) Kill(args *KillSignal, reply *int) error { log.GlobalLogger.Info("接收到自杀信号:", *args) // 1 杀死 rosbag record 命令 ChannelKillRosRecord <- 1 // 2 杀死所有 ros 订阅者 ChannelKillSubscriber <- 1 // 3 杀死上传任任务 if args.DropUploadData == true { // 3-1 等待上传结束再杀死 ChannelKillMove <- 1 ChannelKillConsume <- 1 } else { // 3-2 直接杀死 ChannelKillMove <- 2 ChannelKillConsume <- 2 } go killDone(args.Restart) return nil } func WaitKillSelf() { killService := new(KillService) err := rpc.Register(killService) if err != nil { log.GlobalLogger.Error("注册rpc服务失败:", err) return } // 等待并处理远程调用请求 for { conn, err := commonConfig.KillSignalListener.Accept() if err != nil { continue } go rpc.ServeConn(conn) } } func AddKillTimes(info string) { MutexKill.Lock() switch info { case "1": log.GlobalLogger.Infof("已杀死record打包goroutine,当前自杀进度 %v / %v", KillTimes, KillChannel) ChannelKillDiskClean <- 1 KillTimes++ close(ChannelKillRosRecord) case "2": log.GlobalLogger.Infof("已杀死bag包数量维护goroutine,当前自杀进度 %v / %v", KillTimes, KillChannel) KillTimes++ close(ChannelKillDiskClean) case "3": log.GlobalLogger.Infof("已杀死rosnode和ros订阅者goroutine,当前自杀进度 %v / %v", KillTimes, KillChannel) KillTimes++ close(ChannelKillSubscriber) case "4": log.GlobalLogger.Infof("已杀死bag包移动goroutine,当前自杀进度 %v / %v", KillTimes, KillChannel) KillTimes++ close(ChannelKillMove) case "5": log.GlobalLogger.Infof("已杀死bag包消费goroutine,当前自杀进度 %v / %v", KillTimes, KillChannel) KillTimes++ close(ChannelKillConsume) } MutexKill.Unlock() } func killDone(restart bool) { for { time.Sleep(time.Duration(1) * time.Second) if KillChannel == KillTimes { if restart { _, err := util.ExecuteWithPath(commonConfig.LocalConfig.RestartDir, commonConfig.LocalConfig.RestartCmd) if err != nil { log.GlobalLogger.Info("启动新程序失败,【path】=", commonConfig.LocalConfig.RestartDir, "【cmd】=", commonConfig.LocalConfig.RestartCmd, ":", err) os.Exit(-1) } } log.GlobalLogger.Info("程序已被更新,正常退出") os.Exit(1) } } }