zmq_ctx_term()在关闭套接字时会阻塞。

6

我正在使用ZMQ并在销毁上下文时遇到了问题。

我的代码如下

zmq_ctx_shutdown(context);
zmq_ctx_term(context);

这段代码总是在zmq_ctx_term()上阻塞,并且使用zmq_ctx_destroy()也会阻塞; 然而,如果删除该调用并仅使用关闭调用,则似乎一切正常工作,但应用程序将泄漏未释放zmq上下文的内存。
在我的代码中,我有四个套接字:两个ZMQ_PAIRinproc套接字,用于主线程和具有ZMQ_REP套接字的线程之间的通信,以及在主线程上运行的ZMQ_PUB
我已经在所有这些套接字上设置了ZMQ_LINGER为0,因为似乎只有当我调用zmq_close()关闭所有套接字并返回无错误后,zmq_ctx_term()调用才会阻塞。另外,如果我只调用zmq_ctx_new(),创建套接字,然后调用zmq_ctx_shutdown(); zmq_ctx_term();,这种阻塞仍然会发生。
我担心的是,在使用两个inproc套接字在具有相同zmq上下文的线程之间进行通信时出现了问题,尽管似乎没有与通信相关的任何问题,因为消息正在被接收。
在担心可能存在线程安全问题之后,我发现ZMQ上下文应该是线程安全的,但套接字则不是。我已经检查过,在主线程中,我正在打开和关闭ZMQ_PUB套接字和inproc套接字。在另一个线程中,我正在打开和关闭ZMQ_REP套接字和inproc套接字的另一端,因此似乎这不应该是一个问题。
为了澄清,我正在使用从GitHub(提交d35473e)的当前主分支中的libzmq编写C代码。我确实看到了类似的问题,当链接ZMQ的共享库时,尽管无论我使用静态库还是共享库,都会出现这种情况。我目前正在OS X 10.9上运行。
如果有人有时间查看整个代码,则相关文件在此处列出here
这里有什么问题?

虽然文档上写着(在 zmq_ctx_shutdown):“这个函数是可选的,客户端代码仍然需要调用 zmq_ctx_term 函数来释放 ZeroMQ 分配的所有资源。”,但我也遇到了麻烦。如果我调用了 zmq_ctx_shutdown,我目前并没有执行 zmq_ctx_term(参见 https://github.com/zeromq/clrzmq4/blob/master/ZContext.cs#L251)。 - metadings
@metadings,我没有遇到任何问题,除了没有调用zmq_ctx_term导致内存泄漏外,事实上,直到我阅读了zmq_ctx_shutdown的文档之前,我都认为我做得很对。但是,在您的“Shutdown”调用中似乎不应该将上下文设置为空指针,因为它仍然需要终止。 - Daniel Underwood
当在 zmq_ctx_term() 上被阻塞时,堆栈跟踪看起来是什么样子的? - Xaqq
@Xaqq 我能看到的最后一个调用是 poll()epoll() 调用,我认为这些调用来自于阻塞套接字,尽管我不得不发送 SIGINT 来停止执行,所以我不确定是否会影响任何事情。目前,即使我在调试模式下构建,zmq 调试符号也无法显示出来,所以我正在努力弄清楚发生了什么。 - Daniel Underwood
1个回答

5

观察:

我遇到了同样的问题。尽管我关闭了ZMQ_REQ类型的套接字,并且zmq_close()返回0,但zmq_ctx_term()仍然会被阻塞。这只发生在向未运行的对等体发送消息之后。

zmq_send()会立即返回,但zmq_recvmsg()会超时。

随后我关闭了套接字并调用了zmq_ctx_term()。显然,尽管zmq_close()返回0,但已发送的消息仍然在传出队列中,因此zmq_ctx_term()会被阻塞。

解决方案:

我通过将ZMQ_LINGER选项设置为ZMQ_RCVTIMEO值的一半来解决了这个问题。这种行为实际上在这里描述:http://api.zeromq.org/4-0:zmq-ctx-term


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接