jeffbass / imagezmq

A set of Python classes that transport OpenCV images from one computer to another using PyZMQ messaging.
MIT License
1.01k stars 160 forks source link

zmq.error.ZMQError : Address already in use #36

Closed omartin2010 closed 4 years ago

omartin2010 commented 4 years ago

Great job Jeff. Love this. As I'm using this in my scenario, I may need to sometimes deallocate the streamer and reallocate it depending upon the circumstances. I get this failure:

Traceback (most recent call last):
  File "src/detector.py", line 718, in async_stream_video
    REQ_REP=False)
  File "/usr/local/lib/python3.6/dist-packages/imagezmq/imagezmq.py", line 53, in __init__
    self.init_pubsub(connect_to)
  File "/usr/local/lib/python3.6/dist-packages/imagezmq/imagezmq.py", line 75, in init_pubsub
    self.zmq_socket.bind(address)
  File "zmq/backend/cython/socket.pyx", line 550, in zmq.backend.cython.socket.Socket.bind
  File "zmq/backend/cython/checkrc.pxd", line 26, in zmq.backend.cython.checkrc._check_rc
zmq.error.ZMQError: Address already in use

when I run this portion of my code more than once :

while True:
    video_streamer = imagezmq.ImageSender(connect_to=f'tcp://*:{target_port}', REQ_REP=False)
    # Do some work...
    video_streamer = None

Whenever it hits the 2nd line another time, I get the traceback above. Any idea how to specifically free this (I'm not myself familiar with pyzmq). But I would have imagined some kind of a context management :

with imagezmq.ImageSender(...) as sender:
   # do stuff

But I'm not seeing this in the source code, but if there's missing cleanup code, we would need to implement that too. Thoughts? Did I miss something? Is there an easy way to clean up sockets from this object? thanks!

omartin2010 commented 4 years ago

Fixed my own issue:

video_streamer.zmq_socket.close()

Hope this can help someone. I think this is enough to make it work well, but I've not tested extensively. Enough for my project to work.

jeffbass commented 4 years ago

Hi @omartin2010, I'm glad you found the workaround. Closing the socket is exactly what is needed to allow a 2nd instantiation of imagezmq.ImageSender().

You have found a definite bug in imageZMQ. My own use cases and testing never needed to re-instantiate the ImageSender(). There is, of course, a similar fault in ImageHub(). Thanks for submitting this issue.

I will fix this bug by adding the appropriate def __exit__(self, *other_stuff) that includes zmq_socket.close(). It will take me a few days, since I need to implement it and test it in a significant number of test programs.

In the meantime, your fix should work fine. I will leave this issue open in case someone else runs into this problem and needs your workaround.

Thanks again for finding this bug AND for providing the solution. Jeff

jeffbass commented 4 years ago

Hi @omartin2010 , I have fixed the use of imageZMQ classes in with statements. The statement with imagezmq.ImageSender() should work OK now. I fixed this in the most recent imageZMQ version 1.1.1.

I also added a close method in imageZMQ version 1.1.0, so that closing the zmq socket and context are done in a single method. So you can do this: video_streamer.close(), which is more intuitive. But, when you use the with statement, the close method is called for you, which is how the with statement context should work.

Could you test that this newest version with your original with statement idea? Both the GitHub version of imageZMQ and the version on PyPI are fixed now.

Thanks, Jeff

jeffbass commented 4 years ago

Thanks again for finding this issue. It's fixed. Let me know if you have any further problems with it.

omartin2010 commented 4 years ago

will do - for now I'm working on another section of my project, but I will get back to the one where I use the streaming soon, and I'll update the code to use the with statement versus deleting the object. Thanks for the fix!