使用 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主动.被动关闭时发 ...
随机推荐
- Ant Design 分页数据回显问题
我们可以创建一个新的值来保存这些数据allSingleSelectedRowKeys: 下面是我们的HTML结构 <a-table :row-selection="{ selected ...
- 深入理解snp-calling流程——转载
------------恢复内容开始------------ GATK4流程 准备配套数据 明确参考基因组版本!!!b36/b37/hg18/hg19/hg38,记住b37和hg19并不是完全一样的, ...
- 使用LitJson输出格式化json文件到本地
百度上搜了半天,竟然没有C#使用LitJson格式化输出的例子,全都是Newtonsoft.Json的,最后在litjson的官网找到了方法. 给大家分享一下: https://litjson.net ...
- 编辑器(Editor) vs 集成开发环境(Integrated Development Environment,下文简称 IDE)
编辑器(Editor) vs 集成开发环境(Integrated Development Environment,下文简称 IDE) 经常看到一些程序员拿编辑器和 IDE 进行比较,诸如 Vim 比 ...
- js之对象处理
数据拼接一: 原始数据为对象 { 0grade: "" 0home: "萍钢四切(边部钩痕)" 0price: "3200" 0produc ...
- vim多行缩进
1.首先设置vim缩进空格 vim /etc/vim/vimrc 或者vim /etc/vimrc,添加一下文字 set smartindent set shiftwidth=4 # 缩进四个空格 # ...
- div 自动滚轮2
HTML: <div class="cal_bottom" style="height:78%;margin-top:2%;overflow:auto;" ...
- 项目:口令保管箱,批处理文件配置.bat
#! python3 import sys import pyperclip PASSWORDS = {'email': 'F7minlBDDuvMJuxESSKHFhTxFtjVB6', 'blog ...
- Expression #1 of SELECT list is not in GROUP BY clause and contains nonag
报错信息: Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'a.rs ...
- 深入理解Java内存(图解)
这篇文章是转自http://blog.csdn.net/shimiso/article/details/8595564博文. 本文分析基于jdk1.8 进入正题前首先要知道的是Java程序运行在JVM ...