I use gunicorn 17.5 with worker_class="gevent", workers=3
, that I start with gunicorn -c config.py my:app
. I just noticed the following error in my logs
2014-04-01 04:48:49 [4297] [ERROR] Error handling request
Traceback (most recent call last):
File "/usr/lib/python2.6/site-packages/gunicorn/workers/async.py", line 45, in handle
self.handle_request(listener, req, client, addr)
File "/usr/lib/python2.6/site-packages/gunicorn/workers/ggevent.py", line 119, in handle_request
super(GeventWorker, self).handle_request(*args)
File "/usr/lib/python2.6/site-packages/gunicorn/workers/async.py", line 93, in handle_request
respiter = self.wsgi(environ, resp.start_response)
File "/usr/lib/python2.6/site-packages/beaker/middleware.py", line 155, in __call__
return self.wrap_app(environ, session_start_response)
[...]
File "/usr/lib/python2.6/site-packages/mysql/connector/connection.py", line 1083, in cursor
if not self.is_connected():
File "/usr/lib/python2.6/site-packages/mysql/connector/connection.py", line 696, in is_connected
self.cmd_ping()
File "/usr/lib/python2.6/site-packages/mysql/connector/connection.py", line 665, in cmd_ping
return self._handle_ok(self._send_cmd(ServerCmd.PING))
File "/usr/lib/python2.6/site-packages/mysql/connector/connection.py", line 378, in _send_cmd
return self._socket.recv()
File "/usr/lib/python2.6/site-packages/mysql/connector/network.py", line 170, in recv_plain
packet = self.sock.recv(1)
File "/usr/lib64/python2.6/site-packages/gevent/socket.py", line 432, in recv
wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event)
File "/usr/lib64/python2.6/site-packages/gevent/socket.py", line 165, in wait_read
assert event.arg is None, 'This event is already used by another greenlet: %r' % (event.arg, )
AssertionError: This event is already used by another greenlet: (<Greenlet at 0x37ac190: <functools.partial object at 0x2578788>(<socket at 0x37ab9d0 fileno=14 sock=10.174.17.169:, ('173.228.6.207', 18614))>, timeout('timed out',))
A little bit of searching seems to suggest that I might be using some modules that are not monkey patched before being imported or not greenlet compatible. However the mysql connector is pure python and so that seems to imply it is compatible. And worker_class=gevent
seems to call monkey.patch_all()
when initialized. To be sure, I added import gevent.monkey; gevent.monkey.patch_all()
on the first line of my app, but it doesn't help. One last thing I noticed: when I ctrl-c my app, I get this
Exception KeyError: KeyError(36957072,) in <module 'threading' from '/usr/lib64/python2.6/threading.pyc'> ignored
I read online that this suggests monkey patching was done after threading was imported. Any idea how that could happen given the context I mentioned?
In case that can help: my app opens a bunch of mysql connections when it starts but then I make no guarantee that they will be used exclusively -- i.e. I don't have a connection pool with acquire/release semantics, they're just randomly used by incoming client requests. Would it help to have some sort of connection pool? If yes, how to ensure this works nicely with gevent/greenlets?