zmq_close() has no effect after fork()

Description

The sample program binds ZMQ-socket to TCP 5555 port, forks child process, and finally closes ZMQ-socket. Port 5555 is still used after parent's process exit. I can't use zmq_close(), zmq_term() in child. Therefore, I can't release bind()'ed port after fork.

#include <unistd.h> #include <zmq.h> int main() { void* context = zmq_init(1); void* socket = zmq_socket(context, ZMQ_PUB); zmq_bind(socket, "tcp://*:5555"); pid_t pid = fork(); if (pid == 0) { sleep(3600); } else { zmq_close(socket); zmq_term(context); } return 0; }
$ gcc -o main main.c -lzmq $ ./main $ netstat -ntlp | grep 5555 (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) tcp 0 0 0.0.0.0:5555 0.0.0.0:* LISTEN 21016/main

Environment

Debian 6.0, Mac OS X 1.7.

Activity

Show:

Erik Aronesty April 15, 2014 at 4:54 PM

Note, this affects c++ users as well.

Erik Aronesty May 9, 2013 at 2:39 PM
Edited

This hack works for PERL ... preserving open files... killing all open sockets.

opendir(D,"/proc/$$/fd");
while(my $fd = readdir(D)) {
if ($fd > 2 && (POSIX::lseek($fd, 0, SEEK_CUR) == -1)) {
if (POSIX::ESPIPE == POSIX::errno()) {
POSIX::close($fd) if $fd > 2;
}
}
}
closedir(D);

Erik Aronesty May 9, 2013 at 1:58 PM

I have the same issue with router & dealer workers. If you fork the worker, then exit the router, a new router can't start up until the workers are finished... but the workers can't finish because they are waiting to report to the next router. Essentially this is a "fork()" system call issue. And there are lots of reasons you might want to fork a zmq worker.

A new api call like "zmq_post_fork(context)" could work something like: silently close all the dup'ed sockets & free context. It would be roughly equivalent to zmq_term ... but it wouldn't try to flush/wait for the (now invalid) outstanding sockets. Or maybe zmq_term could just be smarter... and know what you mean.

(You would think the new "unbind" might work... but it doesn't... tried it.... at least in Perl it doesn't work.)

Details

Assignee

Reporter

Affects versions

Priority

Created October 6, 2012 at 7:22 PM
Updated April 15, 2014 at 4:54 PM