0

I'm writing a simple module in my Python app to communicate with the server. I use gevent and zeromq socket. This module will run in a thread.

Here is a demo

import threading
import gevent
import zmq.green as zmq


class SocketTest(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.context = zmq.Context()
        self.socket = None
        self.running = False
        self.sock_greenlet = None

    def run(self):
        self.socket = self.context.socket(zmq.DEALER)
        self.socket.setsockopt(zmq.RCVTIMEO, 1000)
        self.socket.connect('tcp://127.0.0.1:9999')

        self.running = True
        self.sock_greenlet = gevent.spawn(self.process)
        print('Starting')
        self.sock_greenlet.join()

    def process(self):
        while self.running:
            print('Wait for data')
            data = self.socket.recv()
            # do something
            print(data)
            gevent.sleep(0.5)

    def stop(self):
        print('Stop app')
        self.running = False
        # I want to ask all greenlets to exit, or kill them
        # gevent.wait(timeout=0)
        gevent.kill(self.sock_greenlet)
        print('End of stop')


def test():
    try:
        app = SocketTest()
        app.start()
        app.join()
    except KeyboardInterrupt:
        app.stop()
        print('Exit')


if __name__ == '__main__':
    test()

When I press Ctrl + C, my app doesn't exit. I understand that my thread is running an event loop. But I don't know how to stop greenlet process properly or kill it.

In main thread, I will call app.stop, is it safe if I access some variables of gevent loop ? ( I want to send a goodbye message to server when my app exits)

shang12
  • 423
  • 5
  • 18
  • Possible duplicate of [Cannot kill Python script with Ctrl-C](https://stackoverflow.com/questions/11815947/cannot-kill-python-script-with-ctrl-c) – Maurice Meyer Nov 20 '19 at 17:12
  • My thread will can exit when `self.running = False` in greenlet `process`, but it be blocked at `self.socket.recv()` – shang12 Nov 21 '19 at 02:22

1 Answers1

0

I use this in all my projects, works great.

if __name__ == '__main__':
    server = WSGIServer(("0.0.0.0", int(port)), app , handler_class=WebSocketHandler)
    def shutdown():
        print('Shutting down ...')
        server.stop(timeout=60)
        exit(signal.SIGTERM)
    gevent.signal(signal.SIGTERM, shutdown)
    gevent.signal(signal.SIGINT, shutdown) #CTRL C
    server.serve_forever()
eatmeimadanish
  • 3,809
  • 1
  • 14
  • 20
  • I must use zeromq socket because my server also uses zeromq. We build a custom communication channel based tcp socket of zeromq. – shang12 Nov 21 '19 at 02:38
  • gevent and zeromq work great together. https://github.com/zeromq/pyzmq/blob/master/examples/gevent/poll.py – eatmeimadanish Nov 21 '19 at 16:18
  • I'm also using zmq.green. Now, my solution is to use poller with timeout. – shang12 Nov 22 '19 at 06:51
  • 2
    `with gevent.Timeout(2, False) as timeout` can alow you to poll on the recieve but continue after the interval and loop back again. It will just queue the message until it can handle it. I use it for websockets. – eatmeimadanish Nov 22 '19 at 16:06