Re: [gevent] Server push on the same socket as client pull

224 views
Skip to first unread message

Denis Bilenko

unread,
Jun 9, 2012, 3:06:49 AM6/9/12
to gev...@googlegroups.com
On Sat, Jun 9, 2012 at 1:10 AM, Paul Caritj <car...@gmail.com> wrote:
> I'm trying to build a websocket app that "spontaneously" pushes data over an
> open websocket connection as well as responding to requests.

> I tried the obvious: launch
> the ws.receive() loop in one greenlet and push messages out through the same
> socket using another greenlet,

This should just work. It's possible to send() message using different
greenlet. In fact, it's OK to push message from different greenlets to
the same websocket.

> but I get:
> error: [Errno 9] Bad file descriptor

This means the socket was closed by the server, maybe your application
closes it somewhere.

Ian Epperson

unread,
Jun 9, 2012, 3:09:12 AM6/9/12
to gev...@googlegroups.com
Another approach would be to use a queue  http://www.gevent.org/gevent.queue.html

Have a send greenlet that sends any data that is passed through the queue, then fill the queue from either the request response or the spontaneous data.

Ian E.

On Fri, Jun 8, 2012 at 2:10 PM, Paul Caritj <car...@gmail.com> wrote:
Hello everyone,

I'm trying to build a websocket app that "spontaneously" pushes data over an open websocket connection as well as responding to requests. (This capability is, after all, one of the reasons for the websocket protocol, is it not?) This is trivial to achieve using a callback-based websocket framework like Tornado, but problematic with gevent.  The most obvious solution would require the impossible (at least when executed serially): unblocking the handler either when a message is received from the client or when one is ready to be sent from the server. I tried the obvious: launch the ws.receive() loop in one greenlet and push messages out through the same socket using another greenlet, but I get:
....
  File "build/bdist.macosx-10.6-intel/egg/geventwebsocket/python_fixes.py", line 22, in readinto
    return self._sock.recv_into(b)
  File "build/bdist.macosx-10.6-intel/egg/gevent/socket.py", line 212, in _dummy
    raise error(EBADF, 'Bad file descriptor')
error: [Errno 9] Bad file descriptor
<Greenlet at 0x10112c730: SockRead(<geventwebsocket.websocket.WebSocketHybi object at, <Queue at 0x10114e490 maxsize=None getters[1]>)> failed with error

 (OS is OSX 10.7.)

I suppose I could also accomplish this if it were possible to poll the socket to see if there is data to be received rather than blocking while I wait for it. But I don't see any such functionality exposed in the gevent-websocket source. Am I missing something? What do you guys recommend?

Thanks,
Paul



--
This email is intended for the use of the individual addressee(s) named above and may contain information that is confidential, privileged or unsuitable for overly sensitive persons with low self-esteem, no sense of humor or irrational religious beliefs. If you are not the intended recipient, any dissemination, distribution or copying of this email is not authorized (either explicitly or implicitly) and constitutes an irritating social faux pas. Unless the word absquatulation has been used in its correct context somewhere other than in this warning, it does not have any legal or grammatical use and may be ignored. No animals were harmed in the transmission of this email, although the yorkshire terrier next door is living on borrowed time, let me tell you. Those of you with an overwhelming fear of the unknown will be gratified to learn that there is no hidden message revealed by reading this warning backwards, so just ignore that Alert Notice from Microsoft: However, by pouring a complete circle of salt around yourself and your computer you can ensure that no harm befalls you and your pets. If you have received this email in error, please add some nutmeg and egg whites and place it in a warm oven for 40 minutes. Whisk briefly and let it stand for 2 hours before icing.

Paul J. Caritj

unread,
Jun 9, 2012, 8:29:46 AM6/9/12
to gev...@googlegroups.com
These are both really helpful responses. Denis, I'm pretty sure I'm not closing the app anywhere (it's basically just a test harness at this point) but I'll think harder to be sure. And Ian, your approach sounds promising too. Not sure why I didn't think of it! I'll check back in once I've had a chance to try your suggestions.

Thanks,
Paul

Matthias Urlichs

unread,
Jun 10, 2012, 10:56:35 AM6/10/12
to gev...@googlegroups.com
On Sat, 2012-06-09 at 11:06 +0400, Denis Bilenko wrote:
> > but I get:
> > error: [Errno 9] Bad file descriptor
>
> This means the socket was closed by the server, maybe your application
> closes it somewhere.
>
That's one possible proximate cause. There are others.

EBADF means "the kernel doesn't have an open file associated with this
file descriptor".

* the FD has been closed
* the FD was never open
* the FD number is invalid, i.e. negative or too large

The usual cause is that your application close()d it (probably in
reaction to an EOF, i.e. the aforementioned server closing the file) and
then did not tell the other threads about it. This is reasonably OK, as
long as the closing thread also sets the file descriptor variable to -1,
which counts as "telling" in my book.

You need to use strace(8) (assuming Linux) to figure out whether this is
a real problem with your code. The call which returns EBADF either uses
-1 as its first parameter (OK) or some non-negative integer (definitely
not OK).

There is absolutely no way to go from a working file descriptor to one
which throws an EBADF without your application code (or a library it
uses) calling close().

(OK, OK – with the exception of exec*()/clone(), if the close-on-exec
flag is set on that descriptor.)


--
-- Matthias Urlichs

Reply all
Reply to author
Forward
0 new messages