3

Basically I have this problem:

I use ZMQ to use a PUB/SUB formal pattern to publish some pieces of data to other programs. First class, i.e. a Server waits for a client to .connect() and when the client connects, Server sends the data to the Client.

I use ZMQ REQ/REP to synchronize Server and Client.

This is Server.py:

class PublishThread (threading.Thread):
def __init__(self):
    threading.Thread.__init__(self)
    socketPub.bind("tcp://127.0.0.1:4002")
    syncservice.bind('tcp://127.0.0.1:5001')
def run(self):
    while True:
        subscribers = 0
        topic = b"PHONEBOOK"
        while subscribers < 1:
            # Here we wait for client to connect. If the client doesn't 
            #connect, this is where this thread will "hang"
            syncservice.recv()
            # Send response to client
            syncservice.send(b'')
            subscribers += 1

        socketPub.send_multipart([topic, data1])
        subscribers = 0

Q1: How can I stop this thread when I want to exit my program?
Because when I want to exit my program, program "hangs" because thread is still running and waiting for a client.
Q2: How do you think that it will be best to implement this?
Q3: Is there any other way than REQ/REP?

halfer
  • 19,824
  • 17
  • 99
  • 186
koci
  • 31
  • 3
  • Add a timeout to the code that hangs – Vasili Syrakis Jun 29 '16 at 14:50
  • This code is far from a **StackOverflow promoted MCVE method** of posting the high quality Questions. Text states (cit.:) "... Server ... Client ... REQ/REP" but no such elements are in code. **Update your Question to contain a fully representative MCVE for both the server & client** that can reproduce the problem you are asking the Community to help diagnose and fix. **This is the StackOverflow preferred way** to constructively solve and discuss any kind of MCVE related issues. Anyway, **welcome to this great Community of knowledge** and feel free to contribute in our way forwards. – user3666197 Jun 29 '16 at 21:33

2 Answers2

2

ZeroMQ is a very powerful set of tools for smart distributed applications with messaging and signalling features ready to be "just used" ( if one knows how - anyway, do not hesitate to follow the book ).


A1: First, you need to start design your code-units in a non-blocking, asynchronous mode, so that you can still keep control over your threaded code independently of any internal/external blockers. As a lesson No.1, one has to forget to use just the naked .recv() and mentally switch into zmq.NOBLOCK and/or loop-controlled .poll( nMSECs ) where necessary ( not all ZeroMQ wrappers have such a comfort the pyzmq has, so do benefit from this bonus ).


A2: as a rule-of-thumb, one may use several additional SIG and DIAG messaging ZeroMQ-patterns added to the core-logic of any threaded code-unit. This helps you both in testing and in ad-hoc changes in any kind of internal settings ( effectively adding a distributed CLI interface to your code-unit is cool by-product thereof, isn't it? ) and/or termination of the thread.


A3: Oh sure there is. Whenever one feels a REQ/REP Formal Communication Pattern is the right one, check the book again and re-design the code so that it can survive REQ/REP inability to get itself from de-synced distributed-FSA-stepping once it has silently fallen into de-synced state. Many posts refer to this principal issue.


Epilogue: sharing ZeroMQ-socket instances in threads is strongly discouraged.

Community
  • 1
  • 1
user3666197
  • 1
  • 6
  • 50
  • 92
  • Hi again. Thanks for correcting my error - that was not deliberate. I have re-corrected the spelling again (powerful, graceful, etc. all have one L, not two). Your edit message is again inappropriate, and I would much rather you saw my edits in a positive light, and allow me some leeway to make honest mistakes. My edits are, again, not attacks on your work. All the best. – halfer May 13 '17 at 18:36
  • **Thank you**. This was actually my error. Just 've used a copy/paste. Brain was switched off :o) **Hope you use some ML/NLP lexer**, not to have to read all my historical sins & grammar errors in person :o) Enjoy the weekend, Sir. – user3666197 May 14 '17 at 13:44
0

The best way to stop your thread is to send a shutdown message, create a shutdown property, initialized with a boolean false value, then set it as a condition to run your server (in a while loop, set while !shutdown:) then once your server receives a shutdown request from the client you will modify the value of the shutdown property with true which will stop the while loop and then shutdown your thread.

user3666197
  • 1
  • 6
  • 50
  • 92
Anas EL KORCHI
  • 2,008
  • 18
  • 25
  • I have tried that, but the problem is, that Thread hangs and waits for the Client. So if client doesn't connect, Thread will just hang and wait for syncservice.revc(). So if i close the program, Server will still just wait, because it won't loop through while True all the time.. – koci Jun 29 '16 at 16:03
  • As has been posted in the Answer above, the toys work in a bit more complex way. The ZeroMQ calls `.recv()` and `.send()` above, in the MCVE code, are fortunately **blocking**. Besides the fact, this is not a good design practice in most production-grade software design, this also prevents any thread-level soft-signalling or hard SIG_KILL signalling to succeed. The more due to the fact, that the actual blocking is hidden in a state-of-execution in another threat ( the .Context() instance, belonging to the .Socket() instance ( not necessarily the central one ...) ). Plus the REQ/REP deadlock. – user3666197 May 14 '17 at 13:54