Programming in Plato’s Cave 185 …The third time that Berkeley released a version of make with the same bug present, the hackers at BBN gave up. Instead of fixing the bug in Ber- keley make, they went through all of their Makefiles, found the lines that began with spaces, and turned the spaces into tabs. After all, BBN was pay- ing them to write new programs, not to fix the same old bugs over and over again. (According to legend, Stu Feldman didn’t fix make’s syntax, after he real- ized that the syntax was broken, because he already had 10 users.) The Source Is the Documentation. Oh, Great! If it was hard to write, it should be hard to understand. —A Unix programmer Back in the documentation chapter, we said that Unix programmers believe that the operating system’s source code is the ultimate documentation. “After all,” says one noted Unix historian, “the source is the documentation that the operating system itself looks to when it tries to figure out what to do next.” But trying to understand Unix by reading its source code is like trying to drive Ken Thompson’s proverbial Unix car (the one with a single “?” on its dashboard) cross country. The Unix kernel sources (in particular, the Berkeley Network Tape 2 sources available from ftp.uu.net) are mostly uncommented, do not skip any lines between “paragraphs” of code, use plenty of goto’s, and gener- ally try very hard to be unfriendly to people trying to understand them. As one hacker put it, “Reading the Unix kernel source is like walking down a dark alley. I suddenly stop and think ‘Oh no, I’m about to be mugged.’ Of course, the kernel sources have their own version of the warning light. Sprinkled throughout are little comments that look like this: /* XXX */ These mean that something is wrong. You should be able to figure out exactly what it is that’s wrong in each case.
186 Programming “It Can’t Be a Bug, My Makefile Depends on It!” The programmers at BBN were generally the exception. Most Unix pro- grammers don’t fix bugs: most don’t have source code. Those with the code know that fixing bugs won’t help. That’s why when most Unix pro- grammers encounter a bug, they simply program around it. It’s a sad state of affairs: if one is going to solve a problem, why not solve it once and for all instead of for a single case that will have to repeated for each new program ad infinitum? Perhaps early Unix programmers were closet metaphysicians that believed in Nietzche’s doctrine of Eternal Recurrence. There are two schools of debugging thought. One is the “debugger as phy- sician” school, which was popularized in early ITS and Lisp systems. In these environments, the debugger is always present in the running program and when the program crashes, the debugger/physician can diagnose the problem and make the program well again. Unix follows the older “debugging as autopsy” model. In Unix, a broken program dies, leaving a core file, that is like a dead body in more ways than one. A Unix debugger then comes along and determines the cause of death. Interestingly enough, Unix programs tend to die from curable diseases, accidents, and negligence, just as people do. Dealing with the Core After your program has written out a core file, your first task is to find it. This shouldn’t be too difficult a task, because the core file is quite large— 4, 8, and even 12 megabyte core files are not uncommon. Core files are large because they contain almost everything you need to debug your program from the moment it died: stack, data, pointers to code… everything, in fact, except the program’s dynamic state. If you were debugging a network program, by the time your core file is created, it’s too late the program’s network connections are gone. As an added slap, any files it might have had opened are now closed. Unfortunately, under Unix, it has to be that way. For instance, one cannot run a debugger as a command-interpreter or trans- fer control to a debugger when the operating system generates an excep- tion. The only way to have a debugger take over from your program when
Previous Page Next Page