Server Hacking |
2004-11-05
|
Today was weird bug day. I spent four hours trying to fix a bug that I could not understand at all. It seemed like python and twisted were somehow turning a string into a tuple at some point and I couldn't figure out where. Of course it was a silly bug in the code that went something like this:
keycard.requesterName = componentName,
Python programmers will see the trailing comma and realize that this makes the member a tuple, and not a string as I wanted.
I didn't find the bug easily because I debugged using something like
self.debug('keycard requested by %s' % keycard.requesterName)
which has the generally wanted side effect of just printing the only member in the tuple. So debugging like this makes it look like a string !
However, when you print with two variables:
self.debug('authenticating keycard with id %s for %s' % (keycard.id, keycard.requesterName))
it did show up as a tuple !
Maddening. One of those instances where you finally understand some little line of text in a python manual you read some day.
The second bug was more mystifying. I was debugging authentication using a special component, and when testing it out, all lengths of username/password worked in the HTTP request, except for the ones that had 3 characters for both username and password, which turned the username and password on the server side into empty strings. Totally incredible - dad/mom turned into empty strings, while dad/momm, dad/mo, dad/mommy, daddy/mom, da/mom, and all other combinations worked. I was so floored by this that I didn't even try to look into the bug, and just changed the password's length and get it over with.
Also, my very handy debug cycle of "change code-click reload-try new code" is completely trashed on three levels today. First of all, twisted's rebuild doesn't work as it did anymore, with python complaining about all sorts of issues when objects get rebuild. Second, pychecker doesn't work on dotted imports for some reason when used through the import mechanism. And we need to use the import way because we modify a module's __path__ to bring together different paths containing the same package layout. And third, when restarting a worker, something doesn't get cleaned up correctly, causing bind to return with an "Address already in use". So my debug cycle now consists of "change code - stop worker - restart - repeat five times until it doesn't show a bind error".
At that point you get into a lot of wasted time because you are really working on writing some new code, when you should just stop and fix either of these three issues allowing you to work faster on the actual code.
Anyway, the special authentication component is finished and works well. I created Python bindings for SQuaLe yesterday, then used them from the component. A query gets run every 30 seconds for each client, and when that query returns false the client gets expired. Neat stuff.
We're finally getting to the point where we can just write new components and use them pretty quickly. It's nice to see a good foundation pay off.