I just spent 16 hours debugging a complicated, annoying and frustrating problem involving pages not loading in a database frontend, and being spontaneously logged out of a webmail application.
The culprit was the SQLite library (or its bindings to Ruby) being useless with error messages. An example:
#<SQLite3::CantOpenException: could not open database: unable to open database file>
This is not okay. First off, not saying what file is a little annoying, but thankfully, I can tell which file by context since this program only opens one database. Second, and most grievous, it doesn’t say which system call failed (though I guess it’s open(2)
)
and third, it doesn’t say what error code. There’s a reason errno.h
exists, people! perror
is your friend. A happy little “It didn’t work” exception is no replacement for an exception that could read like this: #<SQLite3::CantOpenException: could not open database important.db: EMFILE: The process already has the maximum number of files open.>
I wouldn’t be hacking about supposing it’s a concurrency and locking issue. I’d be knowing that something’s not closing files like it’s supposed to, like I now know after stracing the process and seeing the real value of errno(3)
.
Don’t do this, folks! Let exceptions carry the most information possible. If you code in C, use perror(3)
.
Now I get to see why my web framework isn't closing the database on a reload.