Skip to content
This repository has been archived by the owner on Dec 27, 2022. It is now read-only.

gevent error when using accross threads #51

Open
alex-v-dev opened this issue Jul 30, 2018 · 5 comments
Open

gevent error when using accross threads #51

alex-v-dev opened this issue Jul 30, 2018 · 5 comments

Comments

@alex-v-dev
Copy link

Hi !

I am using mprpc in a large-ish code base, and it might happen that sometimes rpc calls are made from another thread than the main. Is there anything I can do about this ? This is giving the following error :

File "mprpc/client.pyx", line 138, in mprpc.client.RPCClient.call (mprpc/client.c:2545) data = self._socket.recv(SOCKET_RECV_SIZE) File "D:\_DEV_GIT\avPipe_GIT\avPipe\Dependencies\PyLibraries\MSVC14\gevent\_socket2.py", line 295, in recv self._wait(self._read_event) File "src/gevent/_hub_primitives.py", line 265, in gevent.__hub_primitives.wait_on_socket File "src/gevent/_hub_primitives.py", line 266, in gevent.__hub_primitives.wait_on_socket File "src/gevent/_hub_primitives.py", line 252, in gevent.__hub_primitives._primitive_wait File "src/gevent/_hub_primitives.py", line 46, in gevent.__hub_primitives.WaitOperationsGreenlet.wait File "src/gevent/_hub_primitives.py", line 46, in gevent.__hub_primitives.WaitOperationsGreenlet.wait File "src/gevent/_hub_primitives.py", line 55, in gevent.__hub_primitives.WaitOperationsGreenlet.wait File "src/gevent/_waiter.py", line 151, in gevent.__waiter.Waiter.get File "src/gevent/_greenlet_primitives.py", line 59, in gevent.__greenlet_primitives.SwitchOutGreenletWithLoop.switch File "src/gevent/_greenlet_primitives.py", line 59, in gevent.__greenlet_primitives.SwitchOutGreenletWithLoop.switch File "src/gevent/_greenlet_primitives.py", line 63, in gevent.__greenlet_primitives.SwitchOutGreenletWithLoop.switch File "src/gevent/__greenlet_primitives.pxd", line 35, in gevent.__greenlet_primitives._greenlet_switch error: cannot switch to a different thread

Thanks !

@wosiu
Copy link

wosiu commented Sep 9, 2018

+1
My stack:

  File "mprpc/client.pyx", line 138, in mprpc.client.RPCClient.call
  File "/home/m/OCR/django-upload/env/lib/python3.5/site-packages/gevent/_socket3.py", line 382, in recv
    self._wait(self._read_event)
  File "src/gevent/_hub_primitives.py", line 265, in gevent.__hub_primitives.wait_on_socket
  File "src/gevent/_hub_primitives.py", line 266, in gevent.__hub_primitives.wait_on_socket
  File "src/gevent/_hub_primitives.py", line 261, in gevent.__hub_primitives._primitive_wait
  File "src/gevent/_hub_primitives.py", line 262, in gevent.__hub_primitives._primitive_wait
  File "src/gevent/_hub_primitives.py", line 46, in gevent.__hub_primitives.WaitOperationsGreenlet.wait
  File "src/gevent/_hub_primitives.py", line 46, in gevent.__hub_primitives.WaitOperationsGreenlet.wait
  File "src/gevent/_hub_primitives.py", line 55, in gevent.__hub_primitives.WaitOperationsGreenlet.wait
  File "src/gevent/_waiter.py", line 151, in gevent.__waiter.Waiter.get
  File "src/gevent/_greenlet_primitives.py", line 59, in gevent.__greenlet_primitives.SwitchOutGreenletWithLoop.switch
  File "src/gevent/_greenlet_primitives.py", line 59, in gevent.__greenlet_primitives.SwitchOutGreenletWithLoop.switch
  File "src/gevent/_greenlet_primitives.py", line 63, in gevent.__greenlet_primitives.SwitchOutGreenletWithLoop.switch
  File "src/gevent/__greenlet_primitives.pxd", line 35, in gevent.__greenlet_primitives._greenlet_switch
greenlet.error: cannot switch to a different thread

Moreover, if I understand correctly, client part is not thread-safe at all:

data = self._socket.recv(SOCKET_RECV_SIZE)

It creates one socket per all threads. If few threads writes at the same time, a response might be read by wrong one.
Tell me please if I'm wrong.

@wbthomason
Copy link

I'm running into this error too. Is there any workaround other than keeping the client on the main thread and using message-passing between threads to coordinate calls (which seems like a huge pain)?

@wosiu
Copy link

wosiu commented Apr 11, 2019

@wbthomason
All in all I stopped using rpc for communication between my services (originally I was calling c++ rpc server from a django server). Now I run compiled c++ code directly from python using boost::python. But I guess your case is different.
Afair I ended up with creating separate client and connection before a call and closing it just after a call to ensure one thread at a time. Also, because of some reasons, I switched to msgpack-rpc-python at some point, but now I can't recall why. Anyway, it had its own issues as well.

@wbthomason
Copy link

@wosiu Got it, thanks! I'd incidentally also tried using msgpack-rpc-python and found that it worked for my use case (doesn't crash when used across threads and the worse performance isn't a huge problem for me).

And yeah, my case necessitates some sort of RPC, unfortunately.

Thanks for the info!

@ikuyamada
Copy link
Member

I am not sure that I understand this issue correctly, but the current implementation of RPCClient is not thread-safe. You need to create a client per thread.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants