Monday, August 23, 2010

Isolating the Absence of Errors

‹prev | My Chain | next›

I figured out last night that functions in faye subscriptions are silently swallowing exceptions. I would like to see if there is anything I can do to give voice back to those errors.

But first, I upgrade to node.js 0.2.0 (backing up the previous install):
cstrom@whitefall:~/src$  tar zxf ../Downloads/node-v0.2.0.tar.gz
cstrom@whitefall:~/src$ cd node-v0.2.0/
cstrom@whitefall:~/src/node-v0.2.0$ ./configure --prefix=$HOME/local
cstrom@whitefall:~/src/node-v0.2.0$ mkdir /home/cstrom/local/bin/node.0.1.97
cstrom@whitefall:~/src/node-v0.2.0$ cp -p /home/cstrom/local/bin/node /home/cstrom/local/bin/node.0.1.97/
cstrom@whitefall:~/src/node-v0.2.0$ cp -p /home/cstrom/local/bin/node-repl /home/cstrom/local/bin/node.0.1.97/
cstrom@whitefall:~/src/node-v0.2.0$ cp -p /home/cstrom/local/bin/node-waf /home/cstrom/local/bin/node.0.1.97/
cstrom@whitefall:~/src/node-v0.2.0$ make
cstrom@whitefall:~/src/node-v0.2.0$ make install
cstrom@whitefall:~/src/node-v0.2.0$ node --version
v0.2.0
The only out-of-the-ordinary step in there is supplying a --prefix configure option. That allows me to install the code without root privileges.

With that, I am ready to track down what is happening to those exceptions. I still have my faye server running on 4011. In node-repl, I create a client, then subscribe to a "/foo" channel, supplying a callback that should throw an exception (accessing properties on an undefined variable). Lastly, I publish a message to the "/foo" channel to generate an exception:
node> var faye = require("faye");
node> var client = new faye.Client("http://localhost:4011/faye");
node> var puts = require("sys").puts;
node> client.subscribe("/foo", function(m) { puts("1"); asdf.foo.bar; puts("2"); });
node> client.publish("/foo", "bar");
Sure, enough, when I execute that code, I see output from the first puts, but not the second:
node> 1

Upgrading to the latest node had no effect. I did not really expect it to, but it was worth a shot.

So I start tracking down where the message is published. First I add some print STDERR debug code to Faye.Publisher:
  publishEvent: function() {
var args = Array.prototype.slice.call(arguments),
eventType = args.shift();

if (!this._subscribers || !this._subscribers[eventType]) return;

Faye.each(this._subscribers[eventType], function(listener) {
require("sys").puts("here 1");
listener[0].apply(listener[1], args);
require("sys").puts("here 2");
});
}
Sure enough, I reach the first statement, but not the second when I publish a message:
node> client.publish("/foo", "bar");
node> here 1
1
Ultimately, I work my way back up the stack to Faye.NodeHttpTransport and the request.addListener listener setup method:
    request.addListener('response', function(stream) {
response = stream;
Faye.withDataFor(response, function(data) {
try {
self.receive(JSON.parse(data));
} catch (e) {
require("sys").puts("swallowing nil");

retry();
}
});
});
With that, I see that I have successfully tracked down my exception swallower:
node> client.publish("/foo", "bar");
node> here 1
1
swallowing nil
I suspect that try block is more for handling errors in the JSON data or in the response itself. Certainly it does not expect the listener itself to be bad as it is not defending against my own bad code.

I will stop there for the night and plan to pick up tomorrow attempting to find a way to allow bad code exceptions to bubble up, while still retrying response errors.


Day #204

No comments:

Post a Comment