Wandering Thoughts: Recent Entries

Categories: links, linux, programming, python, snark, solaris, spam, sysadmin, tech, unix, web.

2012-01-28

How I use FvwmIconMan

I've mentioned FvwmIconMan in the tour of my desktop and sort of mentioned part of how I use it, but I've never really explained the details.

As I've set it up, FvwmIconMan is essentially a compact taskbar for my various sorts of terminal windows. In a dense display, it shows the window name for each one (well, the first part of it at least), an indicator if the terminal has been iconified, and an indicator if that terminal has the keyboard focus. This is part of how I work around not having conventional titlebars on terminal windows; the window name information from the titlebar is dumped in small text in the 'taskbar', and through long experience I can pick out the label for the current window pretty easily.

(Possibly I should make the current window more distinctive than it is right now. A lot of my FvwmIconMan configuration, much like a lot of my fvwm configuration in general, dates from days with much slower machines that had much more limited graphics.)

Left-clicking on FvwmIconMan's label for a window toggles whether or not it's iconified. Like other taskbar implementations, an iconified (or 'minimized') window is only present as a label in FvwmIconMan; to deiconify it, I have to go click on the label. This means that I care a lot about finding the window labels for specific windows, and I do two things to help with this. First, the window labels are always sorted into alphabetical order; if and when a window is renamed, the order shuffles (this is very important for my use of xterm's ziconbeep feature). Second, I give my windows very consistent names based on either the host they're on or what I'm using them for (and sometimes both). This scheme usually works okay but breaks down a bit if I have a lot of iconified windows on the same host; usually I don't and this isn't an issue. Lots of non-iconified windows on a single host are generally not a problem because they're directly visible and I usually keep them straight by how they're arranged on the desktop.

(This alphabetical sorting does mean that the label for a particular window isn't in a consistent physical spot; it can jump around wildly depending on what other windows get named or renamed. This doesn't bother me, partly because a lot of my terminal windows come and go rapidly anyways. Non-alphabetical taskbars actually drive me up the wall because I never can find anything once I have more than a few things running, or at least I can only find them by scanning through the entire taskbar.)

Some taskbar implementations only show windows from the current virtual desktop or virtual screen or the like. While I use virtual screens I have FvwmIconMan configured to include all terminal windows, regardless of where they are. Among other things this lets me easily yank terminal windows between virtual screens; I move to another screen, then iconify the window and immediately deiconify it again (windows always deiconify on the current virtual screen) with two clicks on the window's label. I can also use FvwmIconMan to switch to the virtual screen that holds a particular deiconified terminal.

(Iconified terminals aren't on any particular virtual screen; they've been effectively swallowed by FvwmIconMan.)

Sidebar: terminal windows versus Firefox windows

A long time ago I would have confidently told you that I did this for terminal windows, and only for terminal windows, because they were by far my most numerous sort of window and I also often had a lot of them iconified. If I had the iconified windows represented as real icons on the root window, I would run out of space; therefor I condensed them all into a much more compact area. Then my Firefox window habit grew out of control and at this point I often have as many iconified Firefox windows as I have terminal windows.

So why do I have a taskbar for terminals and real icons for Firefox? The simple answer is that useful Firefox window names are too long, whereas I can make xterm window names short enough that I can pack them in very compactly. Because Firefox window names are long, a taskbar that showed enough of the titles to remind me what they were would be too big to be feasible. Instead it actually takes less space to have real icons and count on my spatial memory to remember what the Firefox icon over there is for.

(Well, the spatial memory plus the bit of the start of the window title that fvwm shows me below the actual Firefox icon.)

sysadmin/HowIUseFvwmIconMan written at 01:35:21; Add Comment

2012-01-27

Why metaclasses work in Python

I've covered what you can do with metaclasses (1, 2, 3, 4) and even, sort of, the low level details of how they work (1, 2, 3). But I've never covered the high level view of why metaclasses work, ie what overall Python features make them go (partly because I am so immersed in Python arcana that much of that stuff feels obvious to me, although I doubt it actually is).

To start with, in Python everything is an object and all objects are an instance of something (yes, there are spots where this gets recursive). This includes even things that you wouldn't normally think of as objects, such as functions. Crucially, this includes classes: classes are objects. Any time you have an object in Python, a lot of its behavior is usually provided by whatever it is an instance of (to avoid confusion, I'll call this the type of the object). Classes are no exception to this; a lot of how classes behave is handled by their type, even things like how a new object gets created when you call the class.

(For simplicity, I'm going to ignore old-style Python 1.x classes from here onwards and assume that all classes are new-style Python 2 classes that ultimately subclass object.)

To avoid a point of confusion: classes have ancestor ('base') classes that they inherit from (or just object(), the root class). However, classes are not instances of their base class; we can see why this has to be when we note that a class can inherit from multiple base classes. You can't be an instance of several different things at once. So classes exist in a two-dimensional relationship; they inherit from one or more base classes, and at the same time they are instances of something that provides much of their 'class' behavior. The type of classes (the thing that provides the 'class' behavior) is called type().

(This two dimensional structure can get a bit weird.)

In some languages, the creation of classes is black magic that happens deep in the interpreter and isn't something you can do inside the language (even if the classes are visible as objects). Python has instead chosen to expose the ability to create classes by hand; you you can do this by calling type() with the right arguments (and then binding the class object to a name), just as you create instances of normal classes by calling the class itself. As part of creating classes yourself by hand, you can obviously manipulate class creation; you can create a new class with whatever methods, base classes, and so on you want.

(What's odd about type() is that despite it being a class, you can call it with a single object to get the type of the object.)

Python is also an unusual language in another way; in Python, things like defining functions and classes are themselves executable statements. Python doesn't parse your program, create all the functions and classes, and then start running your code; instead it starts running your code and things like def and class execute on the fly (as does import and so on). So it's natural to have your code running as classes are being created.

The combination of these two things means that Python can easily provide a way to hook your own code into the process of creating the class objects for classes that are written in straight Python, with 'class X(object): ....'. Python is already running code in general when this happens, and the mechanisms of creating classes by hand means it's relatively easy for Python to hand you the bits of the class-to-be so you can modify it and then have everything continue onwards to create a new class. This is why metaclasses can change classes as they are being created.

The other half of why metaclasses work is that Python allows classes to be instances of something other than type(). Since classes get a lot of their 'class' behavior through normal instance method inheritance from type(), a class being an instance of something other than type() lets the other thing intercept or change the normal as-a-class behavior for that class (for example, what happens when you call the class). This is why metaclasses can do things with a class after the class has been created.

python/WhyMetaclassesWork written at 00:39:39; Add Comment

2012-01-26

The drawback of modern X font handling gets mysterious

Back in The drawback of modern X font handling I covered how modern X font rendering happens in the client and so can vary from client to client, going from nice on one client to bad on another. I illustrated this with xterm on Fedora and Ubuntu displaying the same font, Fedora well and Ubuntu badly. I now have a good reason to change to using xterm with modern fonts, so I spent part of today poking at this issue; the results have turned this into a genuine peculiar mystery.

What I have so far:

  • the problem does not happen with all programs on Ubuntu. So far xterm and GNU Emacs have the bad font rendering, but Firefox, gnome-terminal, and TK-based programs such as exmh and tkmsg do not; they render DejaVu Sans Mono just like Fedora does.

  • the problem only happens with some monospace fonts, not all of them. The Ubuntu machine I was testing on has 11 candidate fonts listed by 'fc-list :scalable=true:spacing=mono: family'; seven of them show the problem but four do not.

    (The good four are TlwgMono, Tlwg Typo, Courier New, and FreeMono. Unfortunately my preferred xterm font is DejaVu Sans Mono.)

  • the problem is not the Ubuntu version of xterm, the Ubuntu app-defaults file for xterm, or even the Ubuntu Freetype library; I have built the Fedora xterm and my version of Freetype on Ubuntu and used the Fedora app-defaults, and the bad rendering is still there.

  • I've directly set several fontconfig font rendering options that might be doing this without changing anything; at this point I haven't seen any difference with autohint, weight, embolden, or aspect (the last was a wild shot). Similarly, Xft X resources (cf) do nothing that I can see.

    (Forcing autohint=true actually makes the Fedora font rendering slightly but visibly darker while leaving the Ubuntu rendering unchanged for both the good and bad programs.)

  • the problem doesn't happen with xterm on some FreeBSD machines I have handy; they render DejaVu Sans Mono the good way.

Clearly something mysterious is happening in the depths of the Ubuntu version of Xft or something it calls, but only if it's invoked in the right (or wrong) way. Unfortunately I don't think there's any good way for non-experts to see what font rendering choices are being made (the fontconfig library can be coaxed into some debugging output, but it's pretty much 'exports only' from what I can see), so I have no idea if I'll be able to figure out a solution that lets me use the font I want.

(Changing to gnome-terminal is not a solution for me.)

linux/ModernXFontDrawbackII written at 01:22:55; Add Comment

2012-01-25

The death of system administration: I'm all for it

Recently there was a little Twitter commotion about Julian Dunn's Chef, devops, and the death of system administration (he later clarified his views). Although it may surprise people, my snap reaction to the idea of the death of system administration was 'good'.

(I have a number of other reactions to portions of this debate, but 'good' was my first one.)

Most of what many people think of today as 'system administration' is scutwork, at best boring and uncreative. Racking servers, configuring switches through interminable web or CLI interfaces, running network cables, installing OSes in any way that takes more than about one line of typing, writing an Apache or a mailer or Samba config file yet again, restoring files for people, and so on. That's what I'm talking about. At best these are interesting the first few times you do them; after that, very much not.

(System administration wasn't always this sort of work, but times have changed.)

Unless you really do like spending your time doing that or you feel that that sort of work is all that you have to contribute, you are better off without this near monkeywork. Regardless of what your job is called after 'system administration' goes away and the dust settles, you will have shifted to doing actual engaging and creative work and you'll be contributing much more to your organization's success. As I've written before in a different context, having spare time from ordinary day to day 'system administration' is what you need in order to create the big wins. The ultimate version of this spare time is not to have to do the ordinary day to day gruntwork at all.

As you may have gathered, I am not particularly fond of the scutwork currently involved in a great deal of 'system administration' (although I think there's uses for doing it every so often). As far as I'm concerned, the sooner this sort of system administration dies the better.

(At the same time, let's not fool ourselves. This death of system administration will put a significant number of people out of work, ie those people who are currently well paid to do nothing but this scutwork. Many of them do not currently have the skills to move up in the food chain; they will either move down to be less well paid operations monkeys or have to change fields entirely. This is going to be a wrenching process that will be very unpleasant for the people involved, and we should both have sympathy for them and understand the full implications of this shift we're casually discussing, advocating, and cheering for.)

(As a corollary, if you have junior people in your organization and you believe in this shift you should be working with them to make sure that they're developing the skills they'll need for the future, not just spending all of their time doing scutwork for you. And you should be honest with them about how you see their future.)

sysadmin/SysadminDeath written at 01:48:12; Add Comment

2012-01-24

Why I use exec in my shell scripts

As with the little example yesterday, a fair number of my shell scripts end with running a program and when they do, I almost invariably go the little extra distance and do it with exec. In the old days, the reason to do this was that it used slightly less resources, since it got rid of the shell process and left only the process for the real program you wound up running. But, while I was around then, the reason I use it today isn't that; it's that it lets you freely edit the script while that final program is running.

At this point some of you may be going 'wait, what?' That's because most Bourne shell implementations are a little bit peculiar.

In most interpreted languages on Unix (like Python, Ruby, and Perl), the interpreter completely loads and parses the script file before it starts running it. This means that once your script has actually started running, once that initial load and parse has finished, you can freely change the script's file without the interpreter caring; it will only look at the actual file and its contents again if and when you re-run your script.

Bourne shell implementations have historically not worked this way (and it's possible that it's actually impossible to preparse Bourne shell scripts for some reason). Instead they not only parse the script on the fly as it executes, but also they read the file on the fly as the script runs. This means that if you edit a shell script while it's running you can literally shuffle the code around underneath the script. When the shell resumes reading and parsing the script after the current command finishes, it can be reading from partway through a line, from something that it had already read, or (if you deleted text) wind up skipping over something that it should have run. This often causes the shell script to fail with weird errors or, worse, to malfunction spectacularly. This can happen even if the shell is on the last line of the script.

But if you end a shell script with exec, you avoid this. The actual shell interpreter effectively exits (by turning itself into the actual program) and so there's nothing there to try to read anything more and get confused by your edits.

(Of course nothing helps if you can't use exec; then you just have to remember to never edit the script while it's running, at least with an editor that overwrites the file in place.)

Sidebar: a detailed example of what happens

Let's start with a little script:

#!/bin/sh
echo "a"
firefox

Run this script. While Firefox is running, edit it so that the echo string is four or five characters longer (using vi or some other editor that overwrites files in place). When you exit Firefox, the script will complain something like 'script: line 4: efox: command not found'.

When the shell was running Firefox, its read position in the file was just after the newline at the end of firefox. When you edited the script and added more letters, that same byte position was now pointing to the e in the 'firefox'. When Firefox exited and the shell resumed reading from that byte position, it read 'efox<newline>', saw a perfectly valid command execution, and tried to run 'efox' (and failed).

(It reports that this happened on line 4 because it knew it had already read three lines, so clearly this is line 4. As a corollary, you can't trust the line numbers that are printed when something like this happens.)

programming/WhyShellScriptExec written at 00:06:12; Add Comment

2012-01-23

Every so often, I solve a problem with a hammer

For reasons beyond the scope of this entry, I maintain a special Firefox profile and instance for uploading pictures to my Flickr account. Back in the old days, Firefox had a very convenient behavior for this: when it asked you to choose files to upload in an upload form, the default directory was the current directory that you'd started Firefox in. This meant that I could cd to the day's photo directory, start my Flickr Firefox instance, and have the GTK file chooser dialog start in exactly the right directory. Then at some point Firefox changed this so that the default file chooser directory was something like your configured download directory.

I poked at this off and on but couldn't find a way to make Firefox get its old behavior back. So recently I decided to fix the problem with brute force. The script that I use to start my Flickr Firefox instance now looks somewhat like this:

#!/bin/sh
ln -nsf $(pwd) $HOME/CURDIR
exec firefox -P flickr "$@"

This is inelegant and not a real solution, but it makes things a lot more convenient; it's now much faster to navigate to exactly where I want to be. Sometimes that's the right way to deal with a problem, when either the real solution is too much work or the problem is too small to justify anything more than a quick hack.

(I suppose that this could be slightly improved by putting the symlink directly in the download subdirectory. I'm not sure why I didn't do that.)

sysadmin/SolvingProblemsWithHammers written at 00:15:48; Add Comment

2012-01-22

My view of the purpose of object orientation

A while back I read Rise and Fall of Classic OOP. This caused me to realize that I am kind of a heathen as far as object oriented programming is concerned, probably because I came to explicit OO late and never actually learned how to do it the 'right way'. You see, to me object orientation is a technique for code organization and nothing more.

This gives me a very pragmatic view of when to write OO code and when not to; I use objects and classes where they make my code simpler, and I don't use them when they don't. I don't consider them something that has to be followed at all costs or as the only way to model the real world (or any arbitrary artificial world). If the real world entities that you're working with aren't amenable to being wedged into an OO hierarchy, then don't. Given the wide variety of both code structure and ways of organizing code so that it makes sense, it would be fairly absurd to say that OO is always the right answer; it is just one technique among many. Sometimes it's the right answer, sometimes not.

(Of course, some languages as so in love with OO that they don't give you a choice about it; you can't really have freestanding functions and data containers.)

I won't say that all of those OO examples that modeled the real world always struck me as a bit hokey and artificial, because honestly I never really thought that much about it (and any small example is hokey and artificial if you really look at it). But if people are switching towards my view of the purpose of OO, I'm all for it.

(I would be shocked if this was new and novel. I sure hope that lots of people have had this thought before me, because it just feels so obvious.)

programming/ObjectOrientationPurpose written at 02:27:01; Add Comment

2012-01-21

The C juggernaut illustrated

Perhaps it is tempting, looking back at history from the vantage point of today, to say that C succeeded so much because it was at the right place at the right time. As you could tell the story, all sorts of people in the 1980s wanted a low level programming language, C was around, and so they seized on it. Any similar language would have done; it's just that C was lucky enough to be the one that came out on top, partly because of network effects.

(This story is especially tempting to people who don't like C and Unix.)

This significantly understates the real appeal of C at the time, even and especially to people who had alternative languages. A great illustration of this is C on the early Macintosh. You see, unlike environments like MS-DOS (which had no language associated with it, just assembler), the early Macintosh systems already had a programming language; they were designed to be programmed in Pascal (and the Mac ROMs were originally written in Pascal before being converted to assembler).

This was more than just an issue of Apple's suggested language being Pascal instead of C. The entire Mac API was designed around Pascal calling conventions and various Pascal data structures; it really was a Pascal API. Programming a Mac in C involved basically swimming upstream against this API, full of dealing with things like non-C strings (if I remember right, Mac ROM strings were one byte length plus data). I believe that Mac C compilers had to introduce a special way of declaring that a C function should have the Pascal calling convention so that it could be used as a callback function.

Despite all of this, C crushed Pascal to become by far the dominant programming language on the Macintosh. I don't think it even took all that long. Programmers didn't care that dealing with the API issues were a pain; working in C was worth it to them. It didn't matter that Pascal was the natural language to write Mac programs in or that it was a perfectly good language in its own right. C was enough better to displace Pascal in a hostile environment.

C did not win just because it was at the right place at the right time. C won in significant part because it was (and is) a genuinely good language for the job it does. As a result it was the language that a lot of pragmatic people picked if you gave them anything like a choice.

programming/CTriumph written at 01:03:49; Add Comment

2012-01-20

Another Russ Cox regexp article: How Google Code Search Worked

Russ Cox has just added another article in his series on regular expressions; this one is titled Regular Expression Matching with a Trigram Index, or How Google Code Search Worked. It's as worthwhile as all of the previous three.

links/RussCoxRegexpArticlesII written at 12:53:39; Add Comment

2012-01-19

How not to do repeated fields in web forms

There's a certain sort of web form which really wants to make sure that you've entered something correctly, so they ask you to enter it twice in two different fields. You've probably seen this in some web form sooner or later; this is the 'please enter your password again in this field too' or 'please re-enter your email address' field. I tend to think that this is bad on its own, but I've now seen an even worse implementation of this basic idea, which I'll call an anti-confirmation field, one that's practically designed to create errors.

What the people behind this did was quite simple: they made it so that their second fields would not accept pasted input (probably using JavaScript, which I had on because I didn't feel like finding out which bits of the registration process required it). I had to retype both my email address and my password by hand, which was especially annoying because I was pasting both of them from elsewhere. I call this an anti-confirmation field because of course retyping things by hand is more error-prone than pasting things in; in fact, I twice made a mistake retyping the password.

(My web password for this site was a strong random password, as usual. Random jumbles are hard to transcribe accurately by hand, especially when they jump back and forth between character case.)

I suspect that the website designers justified this by saying that they were worried about people entering a bad email address by hand in the first field and then 'confirming' it by just cutting & pasting it into the second field. However, even at its best this logic doesn't work for password fields since browsers don't let you copy the plaintext content of a password field once you've entered it. I also suspect that the designers do not have any actual data on how many genuine errors this prevents (versus how many artificial errors are created).

Sidebar: how to measure the numbers

Assuming that you've committed yourself to (anti-)confirmation fields in the first place, you just need to track field values across time when a submission fails because of mismatched fields. In a transcription error the first of the two fields will turn out to be correct (ie, the same as the final submitted value) and the second field will change. In a genuine error the first field will be different between the failed submission and a subsequent valid one.

Doing this with email addresses raises basically no security issues. If you do this with the password field you'll want to one-way hash them somehow in your tracking data.

web/AntiConfirmationFields written at 22:59:00; Add Comment

Let's make it official: Solaris 11 is closed source

You may remember back in August 2010 when there was a leaked Oracle memo that said, among other things:

We will distribute updates to approved CDDL or other open source-licensed code following full releases of our enterprise Solaris operating system. [...]

At the time I noted that 'full releases' might be construed to be 'Solaris 11' instead of the next 'Solaris 10 update X' release and was unhappy about it. That was then. Now it's been a couple of months since Solaris 11 was officially released to the world and, well:

; cd onnv-gate
; hg incoming
comparing with [...]
searching for changes
no changes found
; hg log | fgrep date | sed 1q
date: Wed Aug 18 15:52:48 2010 -0600

I think it's safe to conclude that there will be no further updates to public (Open)Solaris source code from Oracle, ever. Solaris is now a closed source, 'source-not-available' operating system once again (and probably stronger than it ever was; it used to be sort of possible for universities to get Solaris source code, but I doubt that's on the table from Oracle).

(I'm sure that almost everyone concluded this some time ago. Sometimes I remain hopeful even in the face of all but certain disappointment.)

This matters a lot for us; our ZFS spares system and parts of our ZFS status monitoring system are built around information obtained from undocumented internal library interfaces because there is no other alternative. It seems extremely unlikely that we will ever upgrade to any future version of Oracle Solaris. Lack of (Open)Solaris kernel code also significantly reduces the usefulness of DTrace, one of the theoretical signature Solaris features.

(It is vaguely possible that some version of Solaris will sometime expose public interfaces for the information we need, but frankly I really doubt it. All evidence to date suggests that it is strongly against the engineering culture of ZFS; they had five years to do it and steadfastly didn't. I will skip any number of angry remarks.)

solaris/ClosedSourceSolaris written at 00:43:28; Add Comment

These are my WanderingThoughts
(About the blog)

GettingAround
Full index of entries
Recent comments

This is part of CSpace, and is written by ChrisSiebenmann.

* * *

Atom feeds are available; see the bottom of most pages.

This is a DWiki.
(Help)

Categories: links, linux, programming, python, snark, solaris, spam, sysadmin, tech, unix, web

Search:
[There's more, starting at 2012/01/18 or Previous 11]
(Previous day)
By day for January 2012: 2 3 5 7 8 9 10 11 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28; before January.

Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.