Wednesday, September 1, 2010

Cannot Crash Faye

‹prev | My Chain | next›

Yesterday I eliminated a faye crash by removing an alert() dialog. The alert() dialog blocks event processing in the browser which somehow translates into this:
cstrom@whitefall:~/repos/my_fab_game$ ./game.js
[INFO] Starting up...
[INFO] [init_timeouts] bob 1793694
[INFO] players.update_player_status: bob
[INFO] players.update_player_status: bob
[INFO] players.update_player_status: bob
[INFO] timeout bob!
[INFO] players.drop_player bob

net:678
throw new Error('Stream is not writable');
^
Error: Stream is not writable
at Stream._writeOut (net:678:11)
at Stream.write (net:664:17)
at Object.handshake (/home/cstrom/.node_libraries/.npm/faye/0.5.2/package/faye-node.js:1207:14)
at Object.initialize (/home/cstrom/.node_libraries/.npm/faye/0.5.2/package/faye-node.js:1042:19)
at Object.<anonymous> (/home/cstrom/.node_libraries/.npm/faye/0.5.2/package/faye-node.js:149:28)
at Object.handleUpgrade (/home/cstrom/.node_libraries/.npm/faye/0.5.2/package/faye-node.js:1854:18)
at Server.<anonymous> (/home/cstrom/.node_libraries/.npm/faye/0.5.2/package/faye-node.js:1816:52)
at Server.emit (events:43:20)
at Stream. (http:777:14)
at IOWatcher.callback (net:494:29)
Since I got rid of the alert dialog, I might move on but I cannot be sure that something else might not cause the same problem. Besides, I can still reproduce the error from my javascript console by initiating an alert("foo"). Even though I recently got the server to the point that I can restart without loss, it seems in bad taste to allow the browser an easy means to crash the server.

I find it interesting that the the server seems to always crash at line 1207:
  Faye.WebSocket.Protocol76 = {
handshake: function(url, request, head, socket) {
// ...
socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n', 'binary');
socket.write('Upgrade: WebSocket\r\n', 'binary');
socket.write('Connection: Upgrade\r\n', 'binary');
socket.write('Sec-WebSocket-Origin: ' + request.headers.origin + '\r\n', 'binary');
socket.write('Sec-WebSocket-Location: ' + url + '\r\n', 'binary');
socket.write('\r\n', 'binary');
socket.write(MD5.digest('binary'), 'binary');
}
// ...
}
Why would the Upgrade:... message make it through, but the Connection: Upgrade ... message hang. Odd. I definitely do not know websockets well enough to take a stab at figuring this one out. Instead, I wrap the handleUpgrade() method in a try-catch block to try to isolate the problem originating from the new Faye.WebSocket:
  handleUpgrade: function(request, socket, head) {
try {
var socket = new Faye.WebSocket(request, head),
self = this;
//...
}
catch (e) {
Logging.warn(e);
}
}
Unfortunately, I am no longer able to reproduce the error—at least not creating alerts() from the Javascript console. Typical.

I am unsure if the non-reproduction was caused by the addition of the try-catch block (i.e. it prevented a race condition) or if this is just a very hard bug to reproduce under normal circumstances.

Dissatisfied, I have to call it a night at this point. I may try picking back up with this issue tomorrow, as I am curious about it. Then again, I gave it a go and do have a reasonable workaround already in place. It might be nice to get back to some raphaël.js code or to try out the new version of fab.js. So many interesting things going on...

Day #213

No comments:

Post a Comment