Friday, September 3, 2010

I Love Reading Other People's Code

‹prev | My Chain | next›

Yesterday, I pulled the latest 0.5 branch of fab.js into my own fork. It was a little harder than I expected, but I got through it. Today I plan on exploring it a bit with an eye for getting it working with my (fab) game.

Looking through the example code, I begin to suspect that too much has changed to get it easily working with my comet based code. I think I might have a go at working with the faye version first—it was significantly less (fab), so it ought to be easier getting started with the new stuff.

I am not sure how I feel about the HTML templating code that is in fab v0.5. I have grown to like my templating separate. Still, nothing is preventing me from continuing to use haml.js or jade. It might even be convenient to be able to generate HTML easily from fab. I might kick the tires on that in a day or two.

After a while, I look back to the top of the new (fab) code (who starts reading at the beginning?):
process.on('uncaughtException', function (err) {
console.log('Caught exception: ' + err);
});
Oooh! What on earth does that do? "uncaughtException" sounds as though it might have come in pretty handy when dealing with my faye crashes the other day.

Sure enough, looking through the documentation, it does exactly what it sounds like:
If a listener is added for this exception, the default action (which is to print a stack trace and exit) will not occur.

...

Especially for server programs that are designed to stay running forever, uncaughtException can be a useful safety mechanism.
The documentation also states that this is no substitution for proper try-catch handling, but in this case I am not too concerned. The exception that I was seeing was very hard to reproduce and, now that I have removed a silly alert() from the front-end code that was blocking streams, it could only be triggered by someone very determined to trigger the event. But, if I am catching such events, then I have no need to worry.

So, back in the faye-express branch on which I have been working, I add:
// Don't crash on errors
process.on('uncaughtException', function (err) {
console.log('Caught exception: ' + err);
});

asdf();
The call to the undefined asdf() method ought to trigger my uncaught exception handling function. Except it doesn't:
cstrom@whitefall:~/repos/my_fab_game$ ./game.js
[INFO] Starting up...

/home/cstrom/repos/my_fab_game/game.js:29
asdf();
^
ReferenceError: asdf is not defined
at Object.<anonymous> (/home/cstrom/repos/my_fab_game/game.js:29:5)
at Module._compile (node.js:461:23)
at Module._loadScriptSync (node.js:468:10)
at Module.loadSync (node.js:338:12)
at Object.runMain (node.js:521:24)
at node.js:751:10
That is just a plain old, crashy error message. I am definitely not seeing my "Caught exception" message. What gives?

Unlike last night, my google-fu does not fail me. I come across a thread on the node.js mailing list that suggests that process.on only works with evented code—not on startup. The thread also notes that the example in the documentation is misleading and steps are being taken to address the issue.

For now, I need to move my failure into evented code. Since I was having faye woes the other night, I add my error in the same faye method that was the source of my exceptions:
  handleUpgrade: function(request, socket, head) {
var socket = new Faye.WebSocket(request, head),
self = this;

asdf();
socket.onmessage = function(message) {
//....
};
}
I start up the game, try to add a player to the room (which requires faye messages) and:
cstrom@whitefall:~/repos/my_fab_game$ ./game.js
[INFO] Starting up...
Caught exception: ReferenceError: asdf is not defined
Hrm... I prefer a stacktrace to just the error:
// Don't crash on errors
process.on('uncaughtException', function (err) {
console.log('Caught exception: ' + err.stack);
});
With that, my non-crashing exceptions look like:
cstrom@whitefall:~/repos/my_fab_game$ ./game.js 
[INFO] Starting up...
Caught exception: ReferenceError: asdf is not defined
at Object.handleUpgrade (/home/cstrom/.node_libraries/.npm/faye/0.5.2/package/faye-node.js:1858:5)
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.<anonymous> (http:777:14)
at IOWatcher.callback (net:494:29)
at node.js:764:9
Perfect!

Well this evening certainly did not end up where I expected, but thanks to reading someone else's code, my own got a lot more robust.

Good times.


Day #215

2 comments:

  1. heh, i actually just lifted this from the docs to prevent my heroku instance from crashing.

    http://nodejs.org/api.html#event-uncaughtexception-54

    ReplyDelete
  2. The docs... who knew?

    I love the node docs, but I never paid any attention to the process object (I also see that you're using process.env for the port now). Good stuff.

    ReplyDelete