[zeromq-dev] ZeroMQ correctly forking parent / child worker and cleanly exiting the child

abhay.pradhan at ubs.com abhay.pradhan at ubs.com
Wed Apr 22 15:53:40 CEST 2015


Hello,

Here is what I want to do (C++)

I have a parent process that creates a context and a socket that listens on a port for client requests. A client comes in and asks for an endpoint (port) for a worker node.

At that point, my parent process forks and the forked process creates a worker node that creates another context and a socket that is listening on the worker port. The parent process returns the worker port to the client and now the client is then free to communicate with the worker, giving it tasks.

All of this works.

However, I want the client to be able to send an EXIT message to the worker. At this point, my client should cleanly terminate (closing its worker socket and context). Here is where my problems start


1)      The worker process calling close() on the context throws an assert (line 310 in zmq.hpp)

2)      Once my worker process exits, I cannot get new clients to connect to my parent process. The parent context hasn't been destroyed and the socket is still open (netstat shows LISTENING).

I was wondering if there were tips on how to handle forked processes exiting cleanly. The guide states that I should create contexts and sockets after I fork() however, I do want my parent process to also bind to a port and serve worker ports as endpoints.

cheers
Abhay


// Pseudo code


class Parent {
                void doStuff() {
                                create parent context;
                                create parent socket
                                bool looping = true;
                                bool child = false;

                                while (looping) {
                                                zmq::message_t request;
                                                socket.recv(&request);  // get request from client
            string reqStr = string(static_cast<char *>(request.data()), request.size());

            // should parent exit?
            if (reqStr == "Exit")
                looping = false;

            // configure child and return child's port
            if (reqStr == "Give me worker port") {
                int port = doFork(reqStr);
                            if (port > 0) {
                                string result = NumberToString(port);
                                zmq::message_t reply(result.length());
                                memcpy((void *) reply.data(), result.c_str(), result.length());
                                socket.send(reply);   // send reply to worker
                            }
                            else {
                                // child exiting
                                looping = false;
                                child = true;
                            }
            }
                                }
                                if (!child) {
                                                // parent is getting out
                                    socket.close();
                                    context.close();
                    }

                    // at this point, program essentially terminates .. either the child process or the parent
                }


                int doFork(reqStr) {
                                int port = CreateAPortForChild();
                    switch (pid = fork()) {
                        case -1:
                            cout << "Error in fork";
                            return -1;

                        case 0:
                            LOG(INFO) << "Created child process with pid: " << getpid() << endl;
                            {
                                WorkerPtr workerPtr(new Worker(NumberToString(port)));
                                workerPtr->spawn();
                            }
                            cout << "Child Process exiting on port: " << port << endl;
                            return 0;

                        default:
                            cout << "Parent process. My process id is " << getpid() << endl;
                    }
                    return port;
                }
}

class Worker {
                void spwan() {
                                create child context
                                create child socket

                                bool looping = true;
                                while (looping) {
                        zmq::message_t request;
                        socket.recv(&request);  // Wait
                        string reqStr = string(static_cast<char *>(request.data()), request.size());
                        if (reqStr == "Do Work") {
                                doWork();
                        }
                        else if (reqStr == "EXIT") {
                                looping = false;
                        }
                                }
                                close child socket
                                should i close child context?
                                // child forked process returns to line after workerPtr->spawn()
                                // how do i exit cleanly?
                }
}

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.zeromq.org/pipermail/zeromq-dev/attachments/20150422/36840aa6/attachment.htm>
-------------- next part --------------
Visit our website at http://www.ubs.com 

This message contains confidential information and is intended only 
for the individual named. If you are not the named addressee you 
should not disseminate, distribute or copy this e-mail. Please 
notify the sender immediately by e-mail if you have received this 
e-mail by mistake and delete this e-mail from your system. 

E-mails are not encrypted and cannot be guaranteed to be secure or 
error-free as information could be intercepted, corrupted, lost, 
destroyed, arrive late or incomplete, or contain viruses. The sender 
therefore does not accept liability for any errors or omissions in the 
contents of this message which arise as a result of e-mail transmission. 
If verification is required please request a hard-copy version. This 
message is provided for informational purposes and should not be 
construed as a solicitation or offer to buy or sell any securities 
or related financial instruments. 

UBS Limited is a company limited by shares incorporated in the United 
Kingdom registered in England and Wales with number 2035362.  
Registered Office: 1 Finsbury Avenue, London EC2M 2PP
UBS Limited is authorised by the Prudential Regulation Authority 
and regulated by the Financial Conduct Authority and the Prudential 
Regulation Authority.

UBS AG is a public company incorporated with limited liability in
Switzerland domiciled in the Canton of Basel-City and the Canton of
Zurich respectively registered at the Commercial Registry offices in
those Cantons with new Identification No: CHE-101.329.561 as from 18
December 2013 (and prior to 18 December 2013 with Identification
No: CH-270.3.004.646-4) and having respective head offices at
Aeschenvorstadt 1, 4051 Basel and Bahnhofstrasse 45, 8001 Zurich,
Switzerland and is authorised and regulated by the Financial Market
Supervisory Authority in Switzerland.  Registered in the United
Kingdom as a foreign company with No: FC021146 and having a UK
Establishment registered at Companies House, Cardiff, with
No: BR 004507.  The principal office of UK Establishment: 1 Finsbury
Avenue, London EC2M 2PP.  In the United Kingdom, UBS AG is authorised
by the Prudential Regulation Authority and subject to regulation
by the Financial Conduct Authority and limited regulation by the
Prudential Regulation Authority.  Details about the extent of our
regulation by the Prudential Regulation Authority are available
from us on request.

UBS reserves the right to retain all messages. Messages are protected 
and accessed only in legally justified cases. 


More information about the zeromq-dev mailing list