棋牌游戏项目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.rhkb.cn/news/486290.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GAMES101 完结篇(笔记和作业)

写在前面 我已经把笔记和作业代码放在了GitHub上&#xff0c;欢迎访问GAMES101笔记及作业 (github.com)&#xff0c;如果对你有帮助&#xff0c;欢迎fork or star 下面我想简单介绍一下这里面的东西 Homework Homework文件夹里有0~8的作业框架&#xff0c;参考的其他大佬的代…

uniapp 添加loading

在uniapp中添加loading可以使用uni的API uni.showLoading 方法。以下是一个简单的示例代码 // 显示loading uni.showLoading({title: 加载中 });// 假设这里是异步操作&#xff0c;比如网络请求 setTimeout(function () {// 隐藏loadinguni.hideLoading(); }, 2000);

持续迭代,做一个可以投入项目真正使用的业务容器及插件

问题 上一篇文章中已经可以允许插件中有自己的依赖jar包了&#xff08;原理就是插件中依赖jar包交给插件专属的插件类加载器PluginClassLoader进行加载&#xff0c;业务系统中依赖的jar包交由业务类加载器AliooClassLoader进行加载&#xff09; 大家知道java中是尽可能面向对象…

PostgreSQL数据delete删除恢复

第一部分 文档描述 本文档适用数据表数据被delete类型的删除语句情况下恢复&#xff0c;需要满足数据库或数据表未被vacuum或者vacuum full 第二部分 操作步骤 2.1 创建测试表 创建测试表novels&#xff0c;并插入测试数据 dbtest# create table novels (name varchar(200)…

多线程(二)- Java内置锁的核心原理

前言 Java内置锁是一个互斥锁&#xff0c;这就意味着最多只有一个线程能够获得该锁&#xff0c;当线程B尝试去获得线程A持有的内置锁时&#xff0c;线程B必须等待或者阻塞&#xff0c;直到线程A释放这个锁&#xff0c;如果线程A不释放这个锁&#xff0c;那么线程B将永远等待下…

2024年12月7日Github流行趋势

项目名称&#xff1a;lobe-chat 项目维护者&#xff1a;arvinxx, semantic-release-bot, canisminor1990, lobehubbot, renovate项目介绍&#xff1a;Lobe Chat 是一个开源的现代化设计的人工智能聊天框架。支持多AI提供商&#xff08;OpenAI / Claude 3 / Gemini / Ollama / Q…

群控系统服务端开发模式-应用开发-邮件工厂QQ发送开发

一、邮件发送类实例修改 在Mail目录下修改邮件发送类实例&#xff0c;具体代码如下&#xff1a; <?php /*** 创建邮件发送类实例工厂* User: 龙哥三年风水* Date: 2024/12/5* Time: 14:32*/ namespace Mail; use app\model\param\Emailsms; use Error\BaseError; use Mail…

Golang内存模型总结1(mspan、mcache、mcentral、mheap)

1.内存模型 1.1 操作系统存储模型 从上到下分别是寄存器、高速缓存、内存、磁盘&#xff0c;其中越往上速度越快&#xff0c;空间越小&#xff0c;价格越高。 关键词是多级模型和动态切换 1.2 虚拟内存与物理内存 虚拟内存是一种内存管理技术&#xff0c;允许计算机使用比…

ASP.NET Core8.0学习笔记(二十五)——EF Core Include导航数据加载之预加载与过滤

一、导航属性数据加载 1.在EF Core中可以使用导航属性来加载相关实体。 2.加载实体的三种方式&#xff1a; (1)预先加载&#xff1a;直接在查询主体时就把对应的依赖实体查出来&#xff08;作为初始查询的一部分&#xff09; (2)显式加载&#xff1a;使用代码指示稍后显式的从…

MATLAB Simulink® - 智能分拣系统

系列文章目录 前言 本示例展示了如何在虚幻引擎 环境中对四种不同形状的标准 PVC 管件实施半结构化智能分拣。本示例使用 Universal Robots UR5e cobot 执行垃圾箱拣选任务&#xff0c;从而成功检测并分类物体。cobot 的末端执行器是一个吸力抓手&#xff0c;它使 cobot 能够拾…

环形链表 (简单易懂)

给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&#xff08;…

【C++】奇偶数判断题的高级分析与优化

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;1. 题目描述题目背景 &#x1f4af;2. 基本解决思路示例分析 &#x1f4af;3. 原始代码分析代码分析代码优点代码缺点 &#x1f4af;4. 教师代码及其优化分析代码分析代码优…

1.1 Beginner Level学习之“创建 ROS msg 和 srv”(第十节)

学习大纲&#xff1a; 1. msg 和 srv msg 文件是描述 ROS 消息字段的简单文本文件。它们用于为不同语言生成消息的源代码。srv 文件则描述了一个服务&#xff0c;包括两部分&#xff1a;请求和响应。Srv 文件用于生成服务的源代码。msg 文件存储在包的 msg 目录中。srv 文件存…

Linux-笔记---系统文件I/O

1. open函数和close函数 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);#include <unistd.h> int close(int fd); open函数…

红日靶场vulnstark 4靶机的测试报告[细节](一)

目录 一、测试环境 1、系统环境 2、注意事项 3、使用工具/软件 二、测试目的 三、操作过程 1、信息搜集 2、漏洞利用Getshell ①Struts 2 s2-045漏洞 手工利用s2-45漏洞 Msf综合利用 ②Tomcat框架(CVE-2017-12615) ③phpMyAdmin(CVE-2018-12613) 构造语句写入冰蝎木…

利用 360 安全卫士极速版关闭电脑开机自启动软件教程

在使用电脑的过程中&#xff0c;过多的开机自启动软件会严重拖慢电脑的开机速度&#xff0c;影响我们的使用体验。本教程中简鹿办公将详细介绍如何使用 360 安全卫士极速版关闭电脑开机自启动软件&#xff0c;让您的电脑开机更加迅速流畅。 一、打开 360 安全卫士极速版 在电…

计算机毕业设计Spark股票推荐系统 股票预测系统 股票可视化 股票数据分析 量化交易系统 股票爬虫 股票K线图 大数据毕业设计 AI

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

本文介绍麒麟信安服务器系统(kylinsec)的安装。

本文介绍麒麟信安服务器系统&#xff08;kylinsec&#xff09;的安装。 下载 在开源欧拉官方找到商业版本的介绍找到相关产品&#xff1a; https://www.openeuler.org/zh/download/commercial-release/ 麒麟信安kylinsec下载地址&#xff1a; https://mirrors.kylinsec.com…

并发专题(10)之FutureTask源码剖析

一、FutureTask介绍 Java创建线程的方式&#xff0c;一般常用的是Thread&#xff0c;Runnable&#xff0c;如果需要处理当前的任务有返回结果的话&#xff0c;需要使用Callable。Callable运行需要配合Future来使用。 Future是一个接口&#xff0c;一般会使用FutureTask实现类去…

ssh远程升级Ubuntu20.04到Ubuntu 22.04

ssh远程升级Ubuntu20.04到Ubuntu 22.04 陈拓 2024/10/16-2024/10/26 1. 简介 本文介绍了如何通过ssh将Ubuntu系统从20.04升级到22.04。 在进行系统升级之前&#xff0c;建议备份重要数据&#xff0c;以防升级过程中出现问题。 2. 更新当前系统 硬件系统架构 当前操作系统版…