使用 zeromq与cppzmq 程序退出遇到的坑
在使用zeromq 退出的时候还遇到一点坑,对于服务deaman(守护进程)化的进程可能会遇到这个问题。
现象:
这个问题导致的现象是服务一旦关闭(stop),就会 core dump,core dump 的信息如下。意思大概是使用了无效的描述符。

(gdb) bt
#0 0x00007f522e2le387 in raise () from /lib64/libec.so.6
#1 0x00007f522e21fbb8 in abort () from /lib64/libec.so.6
#2 0x00000000004d5909 in zmq::zmq_abort (errmsg_errmsg_@entry=0x7f522e37025f "Bad file descriptor") at src/err.cpp :88
#3 0x00000000004d5242 in zmq::epoll_t::add_fd_(this=0x1b25520, fd_efd_@entry=15, events_events_@entry=0x1b28580) at src/epoll.cpp:100
#4 0x00000000004e42e2 in zmq::socket_base_t::start_reapiing (this=0x1b28140, poller_=<optimized out>) at src/socket_base.cpp:1465
#5 0x000000000004ela63 in zmq::reaper_t::process_reap (this=0xlb21580, socket_=<optimized out>) at src/reapercpp:133
#6 0x000000000004ele7c in zmq::reaper_t::in_event (this=0x21b21580) at src/reaper.cpp:104
#7 0x00000000004d508e in zmq::epoll_t::loop (this=0x1b255520) at src/epoll.cpp:206
#8 0x00000000004f0d45 in thread_routine (arg_=0x1b255778) at src/thread.cpp:257
#9 0x00007f522f23dea5 in start_thread () from /lib64/libpthread.so.0
#10 0x00007f522e2e6b0d in clone () from /lib64/libc.so.6
产生的原因:
我们服务的 Server 是个 static Instance 单例,在 Server 里默认分配内存的方式声明了 zeromq 的 Context 和 socket。Server 单例创建的时候,就会创建好 Context 和 socket。
class Server
{
....
private:
zmq::context_t m_context;
zmq::socket_t m_socket;
}
在启动服务后,会判断是否需要守护化(daemon化),如果需要,就会 fork 进程并创建守护进程,主进程退出。
正是主进程退出时没有调用 Context 的销毁函数,导致子进程退出时,虽然处理了 Context 的销毁,但是主进程创建的 Context 却没有调用销毁函数,导致和 zeromq 内部线程还在访问失效的描述符,从而出现了 core dump。这里需要解释一下,在 fork 时,子进程也会拷贝父进程的 static 数据。
下面是关于 fork 后父进程和子进程 static 内存数据的介绍:
在 fork 函数调用时,父进程的内存会被复制到子进程中,包括 static 数据的内存。这意味着子进程也会拥有与父进程相同的 static 数据,但是它们是相互独立的。如果在父进程或子进程中修改了 static 数据,则不会影响另一个进程中的 static 数据。
补充一段static类析构调用时机的介绍:
对于在 C++ 中声明为静态变量的类对象,其析构函数会在程序结束时被调用。具体来说,静态对象的析构函数会在程序退出 main 函数后,动态库被卸载之前,以及进程终止时被调用。
静态对象的析构顺序和构造顺序相反。也就是说,先构造的静态对象后被析构,后构造的静态对象先被析构。这一点需要注意,因为不同的静态对象之间可能存在相互依赖的关系,因此析构顺序可能会对程序的正确性产生影响。
需要注意的是,如果静态对象是在动态链接库中定义的,则其析构函数会在动态链接库被卸载之前被调用。因此,如果静态对象依赖于动态链接库中的其他对象或者库资源,需要注意析构顺序的问题,避免出现资源泄漏或者悬挂指针等问题。
另外,对于静态对象的构造函数和析构函数,需要确保它们不会产生任何异常,否则可能会导致静态对象无法正确地被构造或析构,从而产生未定义行为。
解决方法:
将 m_context 和 m_socket 声明为指针类型,在守护化后的 Init 调用中进行初始化。
private:
zmq::context_t * m_context;
zmq::socket_t * m_socket;
这也给我们一些启示,对于类成员是第三方类,最好声明为指针,在初始化函数里调用初始化。
使用 zeromq与cppzmq 程序退出遇到的坑的更多相关文章
- 【转】C#中WinForm程序退出方法技巧总结
C#中WinForm程序退出方法技巧总结 一.关闭窗体 在c#中退出WinForm程序包括有很多方法,如:this.Close(); Application.Exit();Application.Ex ...
- 自定义Toast、程序退出时Toast也退出、Toast的用法
http://blog.csdn.net/wangqilin8888/article/details/7464806 当我们在一个应用中用到Toaster来做为提示时,发现这样一个问题,当某个条件服合 ...
- C#中WinForm程序退出方法技巧总结(转)
本文实例总结了C#中WinForm程序退出方法技巧.分享给大家供大家参考.具体分析如下: 在c#中退出WinForm程序包括有很多方法,如:this.Close(); Application.Exit ...
- Android项目实战(二):安卓应用程序退出的三种方法
现在的APP退出的时候都不是让用户点击了“后退键”就退出.防止用户点错了后退键而造成的用户体检不好. 一年前搞的Demo代码不见了,重新写下就当是复习和以后直接拿来用把 目前流行的解决一般分为两种: ...
- 程序退出异常_DebugHeapDelete和std::numpunct
前几天程序新加一个功能之后,其中用到了boost的lexical_cast<float>,发现在关闭命令行窗口的时候,程序报错,是程序退出清理时候报的错误. 一开始以为是程序新增的功能有问 ...
- 关于SIGPIPE导致的程序退出
http://www.cppblog.com/elva/archive/2008/09/10/61544.html 收集一些网上的资料,以便参考: http://blog.chinaunix.net/ ...
- [转] 关于SIGPIPE导致的程序退出
PS: 如果服务器程序不忽略SIGPIPE,在某些时候TCP writer收到这个信号,会导致进程退出 The rule that applies is: When a process writes ...
- 如何在程序退出的时候清除activity栈
在公司里接手了一个后期的项目,由于项目前期对activity栈管理的不够谨慎,所以导致了在某些情况下程序退出的时候没有将activity栈清除掉.在网上找到的无非就是那几种例子,都不是最好的解决办法. ...
- C#中WinForm程序退出方法技巧总结
C#中WinForm程序退出方法技巧总结 一.关闭窗体 在c#中退出WinForm程序包括有很多方法,如:this.Close(); Application.Exit();Application.Ex ...
- 初步探究java中程序退出、GC垃圾回收时,socket tcp连接的行为
初步探究java中程序退出.GC垃圾回收时,socket tcp连接的行为 今天在项目开发中需要用到socket tcp连接相关(作为tcp客户端),在思考中发觉需要理清socket主动.被动关闭时发 ...
随机推荐
- 在Unity3D中开发的Rim Shader
Swordmaster Rim Shaders 特点 本资源包共包含两种Rim效果的Shader (1)Rim Bumped Specular. (2)Rim StandardPBR(Metallic ...
- go结构体打印格式化成json
需要用到json.MarshalIndent 方法 官方的注释是: MarshalIndent类似于Marshal,但应用Indent来格式化输出. 输出中的每个JSON元素都将以一个新行开始,该新行 ...
- 【摘】python和它的super
python和它的super 如果用过python2,你一定见过下面这个奇怪的代码 class Mama(object): def says(self): print('i am mama') cla ...
- STL库相关练习代码
第一题: #include <iostream> #include <vector> #include <iterator> #include <string ...
- NPM镜像代理设置
用户目录C:\Users\xxx下建立.npmrc文件,内容如下: registry="https://registry.npm.taobao.org" ELECTRON_MIRR ...
- 用bcftools将多个vcf文件合并成一个vcf文件 或将多个vcf和合并成的vcf文件拆分成单个样本的vcf文件
1. 软件的安装 a. bcftools 的安装 b. bgzip的安装: https://blog.csdn.net/weixin_30471065/article/details/95108525 ...
- Matlab|fastica遇到的问题
fastica 1 安装 FastICA 在matlab代码实现以及运行结果by阳光idol 安装步骤博主阳光idol已经写的很清楚了 FastICA 在matlab代码实现.运行结果及错误调试方法 ...
- vue下载图片
async works(obj) { await this.axios({ method: 'get', url: `entryFormControll ...
- ABAP开发面向对象---类
今日学习ABAP面向对象里面的类,关于构造,继承,实现. 踩坑点:类有抽象的方法,类本身也需要是抽象的,故需要在类申明里面加上ABSTRACT关键字 学习资料为B站翱翔云天老师的 1 CLASS zc ...
- Docker安装(win10)
Docker安装 windows 首先开启Hyper-V Hyper-V 是微软开发的虚拟机,类似于 VMWare 或 VirtualBox,仅适用于 Windows 10.这是 Docker Des ...