Reputation: 4638
I've been struggling with this for hours now. It's a pretty simple app, similar to a basic chat, except the server sends messages to the clients only. The basis of my problem is a memory leak. I tried re-factoring the app to be more stateless. I have followed this guide to tracking memory leaks. I couldn't make much sense of the graphs. I might go more in depth later. Firstly I noticed the disconnect was not firing and it does do some cleanup such as kill the greenlets. Why is the disconnect not firing? If anyone can give me some insight it's much appreciated.
https://gist.github.com/a53d1acc83b06b16d263
from gevent import monkey; monkey.patch_all()
import gevent
import redis
import json
import phpserialize
from socketio import socketio_manage
from socketio.server import SocketIOServer
from socketio.namespace import BaseNamespace
from socketio.mixins import BroadcastMixin, RoomsMixin
r = redis.StrictRedis(host='localhost', port=6379)
class ShoutsNamespace(BaseNamespace):
def listener(self, room):
r = redis.StrictRedis()
r = r.pubsub()
r.subscribe(room)
for m in r.listen():
if m['type'] == 'message':
data = json.loads(m['data'])
self.emit("shouts", data)
def initialize(self):
print 'Connected'
def on_join(self, room):
self.emit("shouts", json.loads(r.hget('ffxi.shouts', room)))
self.spawn(self.listener, 'ffxi.shouts:'+room)
return True
def recv_disconnect(self):
print 'Disconnected'
self.disconnect(silent=True)
class PingNamespace(BaseNamespace):
def on_ping(self, message):
print message
class Application(object):
def __init__(self):
self.buffer = []
def __call__(self, environ, start_response):
path = environ['PATH_INFO'].strip('/')
if path.startswith('static/'):
try:
data = open(path).read()
except Exception:
return not_found(start_response)
if path.endswith(".js"):
content_type = "text/javascript"
elif path.endswith(".css"):
content_type = "text/css"
elif path.endswith(".swf"):
content_type = "application/x-shockwave-flash"
else:
content_type = "text/html"
start_response('200 OK', [('Content-Type', content_type)])
return [data]
if path.startswith("socket.io"):
socketio_manage(environ, {'/ping': PingNamespace, '/shouts': ShoutsNamespace })
else:
return not_found(start_response)
def not_found(start_response):
start_response('404 Not Found', [])
return ['<h1>Not Found</h1>']
if __name__ == '__main__':
SocketIOServer(('216.144.246.171', 443), Application(), resource="socket.io", policy_server=False, transports=['xhr-polling']).serve_forever()
Upvotes: 2
Views: 1874
Reputation: 70
recv_disconnect is firing by the user, not the server. Either you have to make the user disconnect (adding a link or button?) or use events like "beforeunload" or "unload" to call it. In both situations you will need to call socket.disconnect().
Example:
$(window).on('beforeunload',function(){socket.disconnect();});
Hope this helped you a bit.
Best regards,
Andreas
Upvotes: 3