Tuesday, July 22, 2008

Don't trust me; I'm just authority!

Heather says that programming in Visual Studio makes her feel like a tool, but that she might be influenced by "real computer programmy people". Al likes feeling important. So Al is going to talk about a real computer programmy topic that's been on his mind lately, and how it relates to what a tool Heather is. And Al is. Because that is the kind of thing we believe in in this flat. Universal toolishness. Al is a tool; Heather is a tool; Christina might be a tool though we haven't really discussed this; Ed could maybe be a tool, but I think his boxing ability trumps my long-distance running ability, so I should be careful about that; probably most of our guests are tools; you're a tool for reading this, but if I was serving it from my own computer inside the flat you'd be even more of a tool.

Today one of my co-workers mentioned he was trying to find the second-best solution to a problem. The problem was basically that he needed to write and run a daemon under Windows. Computer people, prepare to be bored, because you're not in the majority reading this blog. I'm going to explain some stuff. Most programs you run quit when you terminate your session. On Windows that means logging out (on Unix programs belong to a controlling process, usually a shell, which acts as the session). But sometimes you want a program to keep running after you log off. There could be advantages to this in terms of resource use and security. In our case, only one session is allowed on our Windows server machine at a time (don't ask me about the licensing, I have no idea), so we want various of our programs to run without anyone logged in to the machine to keep it open in case an administrator needs to log in.

Under Unix there is a "magical incantation" required of a program to "daemonize". The program makes a couple of calls into the system and comes out detached from its controlling shell. Now the user can log off the shell and the daemon remains. On Windows daemons are given the more toolish name "Windows Services" and apparently have to be registered with the system in a more involved way. I don't exactly know what this way is, but it's obviously something that's documented and known, as many people have written Windows Services over the last decade or so using all kinds of different tools. The programs also have to be able to follow general instructions given to them by the system (start, stop, and the like). I've never written a Windows Service, but if any of it is particularly difficult to do in standard C, maybe with a separate "installer" to set up some registry junk, I'll eat my hat.

Well, it turns out that writing a Windows Service using the .NET framework is involved enough that Microsoft includes a "Service" template in Visual Studio to make it utterly trivial. At least if you buy an expensive version. My company doesn't. So my co-worker that wanted to write a daemon ended up writing it as a Web Service, which works the same way except that every time the server restarts you have to load a web page hosted by the server and click a button to start it, instead of having it start automatically. Fun.

We discussed this while walking around the west loop on lunch break. The problem, he told me, was that you couldn't write a Windows Service using our cheap version of Visual Studio. This struck me as pretty unlikely. I asked him exactly what about it was impossible, but he didn't know beyond that there wasn't a template for it, as there was in a more expensive version of the product. So tonight I punched in a few queries to Google and came up with at least a couple ways to run any odd program as a Windows Service.

That's a larger-scale example of why the whole experience of Visual Studio seems toolish. I mean, even more than that they don't want you writing daemons unless you pay them $600 (developers, developers, developers, my ass). It lures you into thinking that if it's not in the menu it can't be done. Since I've started using it I've fallen into this kind of thinking at the code level. Habitually restarting Intellisense when it goes away, even when it's unnecessary. And Intellisense, like all the other features, works on its terms and not yours. Between all the auto-completion boxes, un-helpful tooltips detailing function parameters, and those obnoxious red underlines I get because I haven't finished typing my expression fast enough, it's more a pinball machine than an editor. If I happen to reference an identifier before getting around to declaring it (happens all the time... sometimes you don't know you need a method until you need it) the Great Wise Intellisense usually auto-completes it to something long and silly. Who the hell asked it? I certainly didn't. I thought the computer served Al, not the other way around.

The thing is, Intellisense is fast and smart at finding matches. It's great for navigating the stupidly verbose .NET class library (it's probably hard to be less verbose when you're trying to write the One True Class Library, which maybe should indicate it's not the greatest goal). Visual Studio allows me to just flat not think about some rare, inane details when coding. Which is great. I just wish it did these things at my command. Maybe there's even an option for this. But this is beyond options. The nature of programming is that the programmer is in charge of the computer, not the other way around. The nature of programming is that only trivial problems can be found by pointing at menus. Here's what Wikipedia says about creating a daemon on Unix:

The common method for a process to become a daemon involves:
  • Disassociating from the controlling tty
  • Becoming a session leader
  • Becoming a process group leader
  • Staying in the background by forking and exiting (once or twice). This is required sometimes for the process to become a session leader. It also allows the parent process to continue its normal execution. This idiom is sometimes summarized with the phrase "fork off and die"
  • Setting the root directory ("/") as the current working directory so that the process will not keep any directory in use
  • Changing the umask to 0 to allow open(), creat(), et al. calls to provide their own permission masks and not to depend on the umask of the caller
  • Closing all inherited open files at the time of execution that are left open by the parent process, including file descriptors 0, 1 and 2 (stdin, stdout, stderr). Required files will be opened later.
  • Using a logfile, the console, or /dev/null as stdin, stdout, and stderr

And here's what it has to say about Windows Services:

A Windows Service is created using development tools such as Microsoft Visual Studio and Borland Delphi.

Yes. Let the programmers at Microsoft and Borland toil in the underworld, you have business logic to write. I realize this is more a culture thing than a technical thing, but I don't think it's any surprise that it's turned out this way. You don't have to do all the stuff in the Unix article manually; if you want you can find libraries or packages for most languages to make daemon functionality trivial (Perl's Daemon::Generic is pretty good, for example), but you can, as with so many other aspects of Unix, find out how the stuff works and why, and not have the answer be, "Because it helps us sell more $600 copies of Visual Studio."

Anyway, I want to conclude by saying: we software people don't know anything. And if you feel some way about some software you're probably right. If you feel like a tool using Visual Studio, not like a badass that could write anything, that's because it was made to automate common things, not to bring to you an understanding of all the crazy shit computers can do and how. That's what I get most out of programming, anyway. The rest, that's for management to worry about.

No comments: