I coworker of mine is currently reading J2EE Development without EJB, and today he pointed out a couple of very nice quotes from C.A.R. Hoare that are included in a chapter entitled “The Simplicity Dividend”. The quotes are from Hoare’s speech at the 1980 ACM Annual Conference, where he was presented with the ACM Turing Award for that year.
In the first quote, Hoare relates his reaction to a specification for a new version of ALGOL in 1965:
I gave desperate warnings against the obscurity, the complexity, and overambition of the new design, but my warnings went unheeded. I conclude that there are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies.
The first method is far more difficult. It demands the same skill, devotion, insight, and even inspiration as the discovery of the simple physical laws which underlie the complex phenomena of nature. It also requires a willingness to accept objectives which are limited by physical, logical, and technological constraints, and to accept a compromise when conflicting objectives cannot be met.
In the second quote, Hoare gives his opinion on the lengthy project that eventually produced the PL/I programming language:
At first I hoped that such a technically unsound project would collapse but I soon realized it was doomed to success. Almost anything in software can be implemented, sold, and even used given enough determination. There is nothing a mere scientist can say that will stand against the flood of a hundred million dollars. But there is one quality that cannot be purchased in this way–and that is reliability. The price of reliability is the pursuit of the utmost simplicity. It is a price which the very rich find most hard to pay.
And one last quote, not included in the book, shows that even a career as stellar as Hoare’s had its share of failures:
There was no escape: The entire Elliott 503 Mark II software project had to be abandoned, and with it, over thirty man-years of programming effort, equivalent to nearly one man’s active working life, and I was responsible, both as designer and as manager, for wasting it.
This project spanned several years in the mid-60s. Hoare was doing commercial software development in the days before it was widely appreciated just how challenging software can be, and the whole speech is well worth reading to get the flavor of those times.
I recently came across daemon(1), a neat little GPL utility that will turn any program into a proper daemon. Doing this usually requires a series of calls to semi-obscure POSIX API functions. This is not hard, but only fun the first few times you do it.
Say I have random Perl script
foo.pl that I want to run in the background as a daemon. This can be done with a simple command like:
$ daemon –pidfile /var/run/foo.pid –name foo foo.pl
Presuming, of course, that
foo.pl is in my
fork(), become a session leader,
chdir() to /, and do a bunch of other stuff that is well described in Chapter 13 of Advanced Programming in the Unix Environment.
daemon then runs
foo.pl and waits for it to terminate.
Things now get interesting because I can do:
$ daemon –pidfile /var/run/foo.pid –name foo –running
Which will exit immediately with an exit status of 0 if
foo.pl is running and 1 if it’s not. Once
foo.pl has served my nefarious purposes, it can be easily stopped:
$ daemon –pidfile /var/run/foo.pid –name foo –stop
daemon can do many other useful things that are well described in the man page.
daemon so much I thought I’d use it to run a daemon on a remote host from a Perl script. Doing this requires a bit of Perl that looks something like:
my $dir = `pwd`;
`ssh remotehost daemon –pidfile $dir/foo.pid
–name foo-daemon $dir/foo.pl`;
The only problem with this is that it doesn’t work.
daemon decides that it’s not going to
fork(), so my Perl script waits for
foo.pl to exit rather than running it in the background. A bit of rumaging around the source soon revealed the reason why.
daemon plays nice with
inetd(8), and it knows not to become a daemon if started by either of these programs- essentially because such things will have already been taken care of.
The check to see if
daemon has been started by
inetd(8) is actually done in
libslack and is implemented by the following function:
size_t optlen = sizeof(int);
return (getsockopt(STDIN_FILENO, SOL_SOCKET,
SO_TYPE, &optval, (void *)&optlen) == 0);
So if standard input is a socket which is apparently the case when daemon has been run by
sshd(8), daemon assumes it has been started from
inetd(8) and doesn’t do its whole daemonization routine. Annoying. I tested this by modifying
daemon_started_by_inetd() so that it always returns 0, and sure enough things worked fine.
Personally I think this is a perfect excuse for a new option for
daemon. I’ll have to ask if they will accept a patch. I am a little surprised that no-one has run into this before- I doubt that I’m the only guy writing grubby little Perl scripts that need to run stuff on multiple hosts. More likely there are other ways to do it just as well, or better.