-
• #2
Here is the code (which won't run in isolation) as it requires files too...
var model = { setpoint : 66, timer : 60, temp: [50,50] // counter : 3600 }; var event_cb = { timer : function (t) { model.counter = t * 60; } }; event_cb.timer(model.timer); function tick() { var d = new Date(model.counter * 1000); model.counterstr = d.toString().split(' ')[4]; model.counter -= 1; model.free=process.memory().free; model.usage=process.memory().usage; } setInterval(tick, 1000); function onPageRequest(req, res) { var a = url.parse(req.url, true); /**/ // console.log(a); console.log({sckt:req.sckt}); console.log(req.headers); //console.log(req.method); /**/ var file = a.pathname; if (file == '/') { file = '/index.htm'; } var headers = {}; if (req.method == 'PUT') return put_file(req, res); var f; try { f = E.openFile('www' + file, "r"); } catch (e) { // look for compressed try { f = E.openFile('www' + file + '.gz', "r"); headers['Content-Encoding'] = 'gzip'; } catch (e) { console.log('no file' + file); } } if (f !== undefined) { var mime = 'text/html'; if (file.substr(-2) == 'js') mime = 'application/javascript'; if (file.substr(-3) == 'css') mime = 'text/css'; if (file.substr(-3) == 'ico') mime = 'image/vnd.microsoft.icon'; headers['Content-Type'] = mime; res.writeHead(200, headers); console.log('started:' + file ); f.pipe(res, { chunkSize : 512, end : false, complete : function () { console.log("Complete:" + file); f.close(); res.end(); } }); } else { res.writeHead(404, { 'Content-Type' : 'text/plain' }); res.end("404: Page " + a.pathname + " not found"); } } var server = require('ws').createServer(onPageRequest); var update_model=false; server.on("websocket", function (ws) { ws.on('message', function (msg) { //console.log((msg)); var data = JSON.parse(msg); console.log(data); if ( update_model ) { for (var o in data) { //console.log( o, data[o] ); model[o] = data[o]; if (event_cb.hasOwnProperty(o)) { event_cb[o](data[o]); } } } }); function send_model() { var s=JSON.stringify(model); ws.send(s); s=null; } setInterval(send_model, 1000); }); function start() { server.listen(8080); } start();
-
• #3
Hmm...
dSnd
is basically a queue - when you write to the socket, stuff gets added to it, and then when it's possible to send the data over the socket, the data from it gets sent and it's cleared.Is this a proper 'leak' - as in - you type
quit()
and then leaked variables are reported? Or it's just thatdSnd
keeps growing? If it's growing I'd assume it is because for whatever reason the socket hasn't been able to send the data? Maybe it's closed? That could be a bit of a bug I guess - if it's closed it should error if you try and write to it. -
• #4
Thanks for the reply..
In chrome on the receiving end of the web socket, I can see the json packets coming in 106 bytes at a time, so they are getting sent once... so I wonder if this is a bug related to the fact that the websocket does not close, so the current data gets added to the queue, the most recent addition gets sent, but because the socket is not closed, the queue keeps on growing. Probably not explained myself very well!
I'll have to try the quit() tomorrow..
-
• #5
It's possible, yes... So there's no data being taken off the beginning of
dSnd
even though it's being sent? -
• #6
I just tried this:
var page = '<html><body><script>var ws;setTimeout(function(){'; page += 'ws = new WebSocket("ws://" + location.host + "/my_websocket", "protocolOne");'; page += 'ws.onmessage = function (event) { console.log("MSG:"+event.data); };'; page += 'setTimeout(function() { ws.send("Hello to Espruino!"); }, 2000);'; page += '},2000);</script></body></html>'; var onPageRequest = function(req, res) { res.writeHead(200, {'Content-Type': 'text/html'}); res.end(page); }; var server = require('ws').createServer(onPageRequest); server.listen(8000); server.on("websocket", function(ws) { var count = 0; console.log("Connection upgraded"); ws.on('message',function(msg) { console.log("Message received"); print("[WS] "+JSON.stringify(msg)); }); ws.on('close',function(msg) { if (intr) clearInterval(intr); }); var intr = setInterval(function() { ws.send("Hello "+count++); }, 1000); });
and it works fine - I don't see any leak at all.
However, when I remove
ws.on('close'
and close the connection then it starts to leak memory.So yeah, that's it. I reckon the connection is actually closing properly, we're just accepting
write
s on a closed connection when we should be erroring.I filed an issue: https://github.com/espruino/Espruino/issues/1220
-
• #7
Fixed now. Your code will error after that, and you just need to clear the
send_model
interval onws.on('close'
. -
• #9
It's a linux-only thing. Basically it quits 'nicely', and then runs a quick check for leaked memory afterwards :)
This is running on the linux version of espurino, and will apply to other boards too.
It looks like the dSnd part of the underyling socket is growing each second evert time the
model
is updated...I've tried to do a simplier use case, but have not yet got a simple case working, so I'll just post what I have so far...
the output of
trace()
shows the dSnd string getting larger each iteration...