当前位置: 首页 > news >正文

棋牌游戏项目ctrl + c无法退出进程问题

棋牌游戏项目ctrl + c无法退出进程问题

  • 运行的服务为 user , 启动命令为
cd user && go run main.go
  • 启动之前先加入调试语句
    • go func() { metric.Serve(...) } 打日志
    • app.Run(...) 打日志
  • user/main.go
var configFile = flag.String("config", "application.yaml", "config file")func main() {flag.Parse()config.InitConfig(configFile)log.Println("metric serve")go func() {metric.Serve(fmt.Sprintf("0.0.0.0:%d", config.Conf.MetricPort))}()log.Println("start app")err := app.Run(context.Background())if err != nil {panic("run app error\n")}// 不让进程停止select {}
}
  • 启动之后的终端输出如下
    在这里插入图片描述
  • 但是当输入 ctrl + c 时,退出失败
    • 程序会输出 user/app.go 的调试日志信息
      在这里插入图片描述
  • 调试信息来自 user/app.go , 来看看里面的逻辑
func Run(ctx context.Context) error {// start GRPC serverserver := grpc.NewServer()// 直接go func() {listen, err := net.Listen("tcp", config.Conf.Grpc.Addr)if err != nil {log.Fatalf("Failed to listen on %s: %v", config.Conf.Grpc.Addr, err)}// 因为Serve这里就是阻塞操作,如果不用协程,这里就会一直被阻塞, 下面的信号就无法监听了if err := server.Serve(listen); err != nil {log.Fatalf("Failed to serve: %v", err)}}()c := make(chan os.Signal, 1)signal.Notify(c,// 终止信号syscall.SIGTERM,// 退出信号syscall.SIGQUIT,// 中断信号syscall.SIGINT,// 挂断信号syscall.SIGHUP,)stop := func() {server.Stop()fmt.Println("stop app finish")}// 优雅启动停止for {select {case <-ctx.Done():return nilcase sig := <-c:switch sig {case syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT:stop()log.Println("user app quit")return nilcase syscall.SIGHUP:stop()log.Println("hang up user app quit")return nildefault:return nil}}}
}
  • 该函数在 main.go 中以 app.Run(context.Background()) 的方式调用
    • 里面会起协程 go func() { net.Listen(...) } 并且以 for { select {} } 的方式阻塞
    • 通过管道 c := make(chan os.Signal, 1) 捕捉中断信号如 ctrl + c , 当捕捉 os.signal 成功时会 return nil 结束函数返回给 main()
  • 那么这个代码在输入 ctrl + c 时究竟有没有退出?我们来验证一下
    • 当程序启动会读取 application.yml 启动 grpcmetric
    metricPort: 5854
    grpc:addr: 127.0.0.1:11500
    
    • 启动程序后grep端口
     go run main.gonetstat -lntp | grep -E '5854|11500'
    
    在这里插入图片描述
    • 输入 ctrl + c 结束进程, 并且查看端口
      在这里插入图片描述
  • 可以看到当 app.go 的调试日志信息 user app quit 打印之后 , grpc端口 11500 是正常关闭了
    • 但是 mainmetric 服务未停止
  • 假如,我们将 mainselect {} 去掉,让 metricapp.Run(context.Background()) 的结束而结束,重新再试一遍
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

结论

  • main.go 代码 select {} 去除后,metric.Serve() 将随 app.Run(context.Background()) 结束而结束,因为 app.Run 是 main 唯一的阻塞条件,因此 main 不需要接收信号也能退出
    • 之所以会这样考虑,是因为信号被 app.go 处理了,所以 ctrl + c 没有作用于 main.go
    • 因此 main.goselect 会一直阻塞造成无法退出
http://www.lryc.cn/news/499398.html

相关文章:

  • 论文概览 |《Urban Analytics and City Science》2023.03 Vol.50 Issue.3
  • 前端知识1html
  • Vue03
  • 深入浅出:Gin框架路由与HTTP请求处理
  • C++初阶——模板初阶
  • y3编辑器文档3:物体编辑器
  • Linux-USB驱动实验
  • 【配置查询】.NET开源 ORM 框架 SqlSugar 系列
  • JavaWeb学习--cookie和session
  • Next.js系统性教学:动态路由与并行路由
  • Backblaze 2024 Q3硬盘故障质量报告解读
  • [创业之路-179]:《领先的密码 - BLM核心方法体系与企业实践》主要章节与主要内容
  • uniapp的生命周期
  • 基于 RNN(GRU, LSTM)+CNN 的红点位置检测(pytorch)
  • L2G3000-LMDeploy 量化部署实践
  • verilog编程规范
  • 飞飞5.4游戏源码(客户端+服务端+工具完整源代码+5.3fix+5.4patch+数据库可编译进游戏)
  • 【MySQL】——​​用一文领悟表的增删查改
  • Zabbix监控Oracle 19c数据库完整配置指南
  • 静态路由与交换机配置实验
  • 【jvm】讲讲jvm中的gc
  • openlayers地图事件
  • 杂记9---一些场景git操作汇总
  • Mysql索引,聚簇索引,非聚簇索引,回表查询
  • 【优选算法 二分查找】二分查找算法入门详解:二分查找小专题
  • 如何将CSDN博客下载为PDF文件
  • pdf转word/markdown等格式——MinerU的部署:2024最新的智能数据提取工具
  • 2024年下半年网络工程师案例分析真题及答案解析
  • English phonetic symbol
  • 普及组集训--图论最短路径设分层图