mopemope/meinheld

``meinheld.patch.patch_all()`` does not patch ``threading.local``

defnull opened this issue · 8 comments

Some frameworks (e.g. Bottle and Flask) and maybe applications depend on threading.local for context-local storage. meinheld.patch.patch_all() does not provide a patch for threading.local and therefor is not enough to get these frameworks to work properly.

See bottlepy/bottle#896 for an example.

ydf commented

mopemope commented on 20 Jan 2011

meiheled is designed very simple, It work single thread.And meinheld is not thread safe.
If you want to run task a long time, you're increase the number of processes.

Your quote is not related to this issue.

FYI, meinheld doesn't patch threading too.
So meinheld works nice with bottle and Flask unless you use greenlet (async io) feature of meinheld.

I am not interested in meinheld's greenlet feature, because I use asyncio or golang when I need async.
So I recommend you to use gevent.

Oh, I may wrong. Flask uses greenlet.get_ident().
See https://github.com/pallets/werkzeug/blob/master/werkzeug/local.py

So Flask may works with meinheld even if you use async I/O feature.

Are greenlet (async io) features optional? What happens if I read from environ['wsgi.input']? is that a blocking operation by default?

By default, request body is written into tmpfile or on memory buffer.
After whole body is received, wsgi handler is called.
So reading from environ['wsgi.input'] is on memory operation, or reading from file (blocking).
greenlet switch won't happen during reading from it.

Okay, so why does meinheld.patch.patch_all(), which only patches socket, then causes a thread-change mid request as demonstrated here: bottlepy/bottle#896 ?

Ahh okay, because @kianxineki started an outgoing HTTP request while handling a bottle request, thus using a socket, which suspended the greenlet and caused the issue. Okay, I understand now.