jlm-blog
~jlm

18-Dec-2008

Ubuntu Eee: Not ready for prime-time

Filed under: linux — jlm @ 21:57

On Sunday I bought myself a new toy, an Asus Eee 900. The general opinion on the ’net seemed to be that the default Xandros Linux installed OS was inferior to Ubuntu Eee (note not a Canonical-endorsed project), so I installed it. I’m going to restrict my discussion to the software (you can find a lot written about Asus Eees themselves on the net).

The most serious problem by far is that WiFi was broken out of the box, due to faulty interaction of the wifi-on/-off and wifi-toggle ACPI event handlers. I found plenty of people complaining about this issue and several fixes by basic searching, but it’s utterly astounding to me that an OS distribution targeting a portable computer where WiFi is essential for its use could have this bug in release. The Eee exists to be a box accessing everything through wireless, no WiFi is a “game over, you lose” level bug. It was also made more frustrating by the various networking tools not even showing wireless as an option unless it was already on. Better would be to show the wireless interface as there and down (as it was) and let the user select it to bring it up (which still wouldn’t have worked, but at least you’re not making them waste their time figuring out why it’s not there at all).

There were some issues that popped up earlier, even before the first boot in the install app. The select keyboard layout section has a text area where you can test typing, but it uses the current keyboard layout instead of the new one you’ve selected in the tool, uselessly. (The change keyboard layout tool once you’ve booted into the OS has the same problem.) The time of day shown when you’re selecting the local timezone is wrong (and it says you can set it to the right time after boot), though after booting it gets the time of day correct.

After getting wireless working, the update manager said updates were available, so I let it install them. It got halfway through, then the laptop suspended itself because it was idle. When I un-suspended it, WiFi and X didn’t come back up and asusosd was busying the CPU. Restarting X brought up a login window on virtual console 9 (only discovered by seeing X running on tty9 in ps), but I had to reboot to get WiFi back so the update could finish. (The Eee seems to resume fine when it’s genuinely idle at suspend.)

I copied the photos from my recent vacation onto its SSD, and went to view them in the file viewer you get from the “Pictures” folder. This brought up Eye of Gnome, and as my camera takes more pixels than the Eee’s display has, you have to scroll. Unfortunately, EOG doesn’t scroll when you make the normal scroll touchpad gestures, but instead changes zoom level. Also unfortunately, EOG doesn’t scroll when you press the arrow keys, but instead switches to other pictures in the CWD. So, to scroll in EOG it seems you have to move the mouse cursor to the arrows on the scrollbar and hold the mouse button down, which is a pretty crummy thing to ask of the user of an Eee. Also unfortunately, if you go to the help menu in the file viewer to try and learn how to change the preferred app for pictures to one which doesn’t suck as hard, you get an error dialog saying there’s no help. Also also unfortunately, the “Preferred Applications” tool doesn’t let you change associations for pictures, only for a small handful of apps: Web browser, mail reader, terminal, and “multimedia” (videos & music) player.

Moving on to more minor stuff, at night, I turned the display brightness down, but twice it switched itself back up to full brightness a few seconds later. (Third time turning down seemed to stick, but it happened again this morning and took four turn-downs.) It was getting hot, because it wasn’t turning the fan on. (After installing cpufrequtils, the fan would turn on.) The Firefox start page is set to a file which isn’t installed. mtr needs root to run, and it’s not installed setuid.

The Eee’s “House” key does nothing — naturally, it should bring you back to the home menu display. This would be convenient, as you have to mouse over to the Ubuntu logo on the top left and click it to get there now, and the other top-left icons are available by cycling through Alt-Tab. There are often spurious mouse clicks generated by the touchpad when I’m trying to fine-position the mouse and it thinks I’ve tapped (the mouse should never require fine-positioning, but that seems to be a lost battle), and at the same time actual taps are often misinterpreted as short moves.

I’m not the first to run into these problems, they all seem to have been reported already, but that I’ve run into so many usability and functionality problems in so short a time means that Ubuntu Eee is clearly not ready for mainstream use. A sophisticated user can get around them (X didn’t come back after un-suspend? Alt-F1, login, start new X, ps, ah it’s on tty9, Alt-F9. — mtr can’t get raw socket? sudo chmod u+s =mtr) but it’s too much to expect from non-geeks, and falls well short of the goal of “it just works”. I’m optimistic about the future — hopefully Ubuntu Eee won’t make a release with such a severe bug ever again, and suspend/resume is getting a lot of work on it in the kernel right now, and a lot of this stuff just needs easy fixes (like putting the help files and start page where they’re looked for (Eye of Gnome OTOH has sucked for years and should just be taken out back and shot)). And it’s a pretty nice experience for me as a “power user”, once I’ve patched the wireless and gotten the big initial update complete and got my image viewer set to ImageMagick…, and I can accept the brightness resetting and suspend problems and the “House” key not working for a few more update cycles. But it’ll be a while still before the dreamed-of shiny usable Linux laptop arrives.

9-Oct-2008

IPv6

Filed under: networking — jlm @ 20:02

I set up IPv6 through 6to4, and found it to be surprisingly easy and simple — subject to the major proviso that you only want IPv6 on one box. This should be easy, 6to4 gives you every address from 2002:abc:123:0:0:0:0:0 to 2002:abc:123:ffff:ffff:ffff:ffff:ffff to play with. To get it on other boxes, you need to have the end of the 6to4 tunnel route IPv6 packets, and the end-hosts have to get IPv6 addresses from it. Which turns out to be a problem. It’s easy to give your router 2002:abc:123:0:0:0:0:0, but giving out IPv6 address doesn’t work — the client support for getting IPv6 addresses over DHCP is zilch. Easier to set up Teredo.

This is worrisome. Client vendors have been complaining that the ISPs aren’t deploying IPv6 routing and patting themselves on the back for having their systems support IPv6, without considering that it only works if manually set-up. Suppose some ISP did do all the work of making its network route IPv6 — their customers still aren’t going to be on the IPv6 net, because their computers never ask for IPv6 addresses over DHCP so the ISP never gives them any. Are we expecting each one to call customer support for their IPv6 address and how to tell it to their system? The Internet has as many users as it does because the software lets the computers be plugged together and figure out how to talk on their own, without the user having to know how any of that works. IPv6 can’t work until that’s the case for it as well. If reading an RFC ever enters the picture, you lose: 99.9% of the Internet’s users won’t bother. It has to be made so transparent that the end user needs to do nothing and won’t even notice that another routing protocol is processing the packets.

3-Apr-2008

Regex breakpoints in gdb

Filed under: programming — jlm @ 12:49

gdb has this awesome feature that nobody seems to have heard of (including myself before today). You can set breakpoints by regex!

“help rbreak”

10-May-2007

Tip: compression

Filed under: general — jlm @ 16:28

It doesn’t help to zip already compressed file formats, like jpeg or mpeg, it only wastes CPU. Uncompressed video, audio, or still images will compress better with algorithms which are dedicated for video, audio, or images than they will with general compressors. JPEG is for photos — for images which are line drawings use PNG.

16-Dec-2006

The C aliasing rules

Filed under: programming — jlm @ 11:49

A lot of people are confused by the pointer aliasing rules introduced by C99. (Sometimes called “strict aliasing”.) First, what is aliasing? When two pointers refer to the same location, they’re called “aliases”.
void fcn(int *p) { int *q = p; ... }
Here p and q are aliases. The general rule is that pointers to the same type are allowed to alias, and pointers to different types are not. (Differences like signed/unsigned and const/non-const aren’t considered significant here– they’re all in the same “aliasing class”.)
void fcn(float *p) { int *q = (int *) p; ... }
This is illegal, because p and q are aliases, but one points to float while the other points to int. In practical terms, the optimizer will reorder accesses to *p and *q across each other, or optimize out writing/reading the value back into/from memory, because they’re in different alias classes, and you’ll get mysterious bugs.
There are two exceptions to this rule: void * and char *. Pointers of these two types are allowed to alias any kind of pointer. void * can be assigned from and to any pointer without a cast, but you’re only allowed to assign it to a type which reflects the original pointer (or char *).
void intfcn(void *p) { int *q = p; ... }
void floatfcn(void *p) { float *q = p; ... }
void fcn(void) {
  int i;
  intfcn(&i);  /*  OK: int * -> void * -> int *  */
  floatfnc(&i);  /*  Bad: int * -> void * -> float *  */
}

This style is used a lot in callbacks, where it’ll look something like:
void callsoon(void (*fcn)(void *), void *arg);  /* Call fcn(arg) in one second */
void fcn(void) {
  static int i = 1;
  static float f = 0.1;
  callsoon(intfcn, &i);
  callsoon(floatfcn, &f);
}

The compiler is still assuming your int * and float * pointers won’t alias here: It’s up to you to ensure that the void * which got a float * doesn’t get turned into an int * and vice-versa. The void * is telling the compiler “I can ensure non-aliasing on my own, without you checking”. You should not use it to silence aliasing warnings, because you get those warnings in situations where the compiler is going to re-order accesses, and the void * gives it free license to do so silently!
What do you do when you really need to alias across types? First, don’t do a straight pointer typecast or go through a void * typecast for the reasons above:
void fcn(float *p) { int *q = (void *)p; ... }
void fcn(float f) { int i = *(int *)&f; ... }
void fcn(float f) { int i = *(int *)(void *)&f; ... }  /* All illegal aliasing */

Another common but illegal technique is to go through a union:
union { int i; float f; } x; x.f = f; i = x.i;  /* Illegal: unions can only be read from the last type assigned to them */
So, what do you do? One of the most common use cases is for transferring byte representations, and memcpy() works fine for this (any modern compiler will optimize it into stores).
void fcn(float *p) { int i; memcpy(&i, p, sizeof(i)); ... }  /* Safe if sizeof(int) == sizeof(float) */
void fcn(float f) { int i; memcpy(&i, &f, sizeof(i)); ... }  /* Ditto */

void fcn(float *p) { int *q; memcpy(&q, &p, sizeof(q)); ... }  /* Illegal: just a fancy way of writing q = (int *)p */
If you need fine-grained access, this is where char * comes in. It’s allowed to alias any other pointer, so the compiler can’t re-order pointer accesses across char * accesses unless it can ensure non-aliasing by other means.
void fcn(float *p) { char *q = (char *)p; ... }  /* Safe */
Note that just going though a char * on your way to an illegal alias doesn’t make it legal:
void fcn(float *p) {
  char *q = (char *)p;  /* q now validly aliases p */
  int *r = (int *)q;  /* r now validly aliases q, but p and r are still in different alias classes and *p and *r can be re-ordered across each other */
  ...
}

void fcn(float *p) { int *q = (int *)(char *)p; ... }  /* Illegal aliasing of p and q, same as q = (int *)p */
char * is safe, as long as you do your references through it, as chars (bytes), but just having a char * there doesn’t make non-char * references legal.

7-Nov-2006

What’s wrong with my sound?

Filed under: linux — jlm @ 13:03

The sound on my Ubuntu box stopped working this morning.
I was getting a ton of messages “ALSA lib pcm_dmix.c:819:(snd_pcm_dmix_open) unable to open slave”. I bounced artsd, and it said that very message on startup. After the usual futzing around, such as looking in syslog and finding nothing, I straced it, and searching for dev files noticed:
open("/dev/snd/pcmC0D0p", O_RDWR|O_NONBLOCK) = -1 EBUSY (Device or resource busy)
Well, that certainly looks like a culprit, would have been nice if artsd could have actually reported that as an error.
Now, let’s fuser /dev/snd/pcmC0D0p — huh, the two xpdf’s I’m running have it open. (WTF is xpdf permanently grabbing my pcm device?) Kill the xpdf’s, now artsd can start cleanly, and I have working sound again.
I have no idea how normal users (Ubuntu’s alleged target market) are supposed to handle this. Reboot, most likely. Works for Microsoft.

26-Jul-2006

Haskell vs. C readability stawman

Filed under: programming — jlm @ 17:03

Every time I think about learning Haskell, I head over to haskell.org, read the Introduction link, and am offended by the astoundingly absurd quicksort example they provide for its superiority over C and leave in disgust.

First, let’s take a look at their Haskell implementation of quicksort:

    qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)

Wait one second here! Something’s fishy. At the bottom, the basic operation quicksort does is a swap. Where’re the swaps? I don’t see any swapping. I do see splicing though; quicksort doesn’t splice. This isn’t quicksort; quicksort is an in-place sort, this thing here is a list sort. This is not just an implementation detail, it’s fundamental to what quicksort is. It doesn’t splice, it makes swaps. If you have some linked lists, you sort them with something like mergesort. But for arrays, you can’t beat quicksort.

Now, we can start on the C implementation they provide…

    qsort( a, lo, hi ) int a[], hi, lo;

Huh?

If you’re a C programmer, your first impression is to boggle at this syntax. It’s been deprecated for 17 years, and most C programmers nowadays probably don’t even recognize it. What moth-eaten tome did they dig this out of? Variables of hi and lo and h and l? l+1 and l-1 as expressions? That’s the kind of thing you see at the IOCCC. Let’s choose an actual decent example of quicksort for a more honest comparison, like the one from K&R2:


/* qsort:  sort v[left]...v[right] into increasing order */
void qsort(int v[], int left, int right)
{
    int i, last;
    void swap(int v[], int i, int j);

    if (left >= right)    /* do nothing if array contains */
        return;           /* fewer than two elements */
    swap(v, left, (left + right)/2); /* move partition elem */
    last = left;                     /* to v[0] */
    for (i = left+1; i <= right; i++)   /* partition */
        if (v[i] < v[left])
            swap(v, ++last, i);
    swap(v, left, last);        /* restore partition elem */
    qsort(v, left, last-1);
    qsort(v, last+1, right);
}

Much more readable than that strawman example they have on the Haskell intro page!
But it’s still an apples-to-oranges comparison, because the C implementation is doing a real quicksort, and the Haskell is doing a list sort. Show me a real in-place quicksort in Haskell: It’ll turn out looking almost like the implementation in K&R, I wager.

Now, Haskell was written by people who know their computer science. They know all about quicksort, they know their example is comparing different algorithms, and they can write better C code than what they use. Why do they have to be dishonest when promoting the virtues of Haskell, hmm?

7-Mar-2006

Dvorak HOWTO

Filed under: general — jlm @ 18:37

[Dvorak key layout]

No, it won’t make you type faster (or probably not by much… top speed typists all use Dvorak, but I didn’t notice any improvement) or more “cheaply”, but it is easier on your hands, and reducing finger fatigue makes it a clear winner in my book.

How to switch:
Windows NT:
    Start ➙ Settings ➙ Control Panel ➙ Keyboard ➙ Input Locales ➙ Properties ➙ Keyboard Layout ➙ US-Dvorak
    Hit “OK”, then “Apply”.

Windows 9x:
    Same, but you’ll probably need to insert the install CD when it says, as the layout isn’t part of the default install, so have it ready.

Windows XP:
    Start ➙ Control Panel ➙ Regional and Language Options ➙ Languages ➙ Details ➙ Settings ➙ Default Input Language ➙ United States-Dvorak
    If it’s not availabe, under “Settings” go to Installed Services ➙ Keyboard ➙ Add and select it, then you’ll be able to set it as the default.

Linux console:
    “loadkeys dvorak” will change the current keymap to Dvorak. (Or sometimes “loadkeys dvorak/dvorak”, look around /lib/kbd/keymaps.) Making it the default usually involves setting the “KEYTABLE” attribute in /etc/sysconfig/keyboard to whatever you used with loadkeys.

X11 on PCs:
    xmodmap pentdvor.xmod

X11 on Sun 5x keyboards:
    xmodmap sun5dvor.xmod

Other X11:
    First, run xmodmap -pke > qwerty.xmod so you have the current keymap safely saved in case things get messed up. You’ll want to copy “xmodmap qwerty.xmod” into a cut buffer so you can paste it with only the mouse.
    Run xmodmap q2d.xmod
    This maps the Qwerty keysyms to Dvorak, and can fail sometimes, like if two keycodes generate one of the moved keysyms. Because it operates on keysyms, not keycodes, this file will rearrange your keyboard again if you run it twice, producing garbage. Good thing you have that recovery command in the cut buffer, right?
    You can save the keymap you produce with q2d with “xmodmap -pke > dvorak.xmod” and return to it with “xmodmap dvorak.xmod” after that. If you’re not quite happy with it, you can tweak the xmod file yourself, or get the “xkeycaps” program which will do it for you.

30-Jan-2006

screen tutorial

Filed under: linux — jlm @ 19:37

screen is really simple to use, but it can be hard to get started. It has so many features that the essentials get lost if you try (say) to read the manual. So here they are:

1: Start a new session with screen

This is the first thing to do, but it’s confusing, because when you do it you just get a shell prompt again. What happened? You’re actually in a new shell, inside of screen. To demonstrate, start a long-running command, like cat. Leave it up, and go on to

2: Detach from inside screen with “Ctrl-A d”

You should get a message saying screen detached and a shell prompt. This is the prompt from your old shell: It actually ran the command screen, the stuff between then and now was all inside screen, and now the screen command just exited and we’re back at the old shell. Now you can do whatever, log off, log back in, just don’t reboot, then

3: Reattach screen with screen -r

Hey, hey, we’re back where we were when we ran screen in step 1, and our cat is still there waiting for input! That’s the most fundamental concept, the core of screen: It keeps these pseudo-terminals going for you, while you log off, go to bed, switch computers, whatever. There’s a parent “SCREEN” process that screen made, and as long as that process sticks around, you can go back to your pseudo-terminals with screen -r. There’s one other fundamental:

4: Detach from outside screen with screen -d

When you try to reattach a session which screen already has attached elsewhere, it gives you an error. (Try it from another shell.) Maybe the network kills your connection while you’re in screen. Maybe you absent mindedly left it attached from visiting the Timbuktu regional office. Maybe you had to leave in a hurry and couldn’t do petty housekeeping like detaching your session. But you need to reattach that session here. So screen -d will detach the old connection, and now you can screen -r freely. Try it!

That’s the ultra-basics. When you’re comfortable with them, you can read about how to do copy and paste, multiple windows, multi-display, and lots of other useful features… At leisure. You’ve got the core now.

6-Jan-2006

C++ style

Filed under: programming — jlm @ 21:44

In C, you only have call-by-value (with some wierdness for arrays). To pass a reference, you explicitly take the variable’s address. This has the benefit that you can easily tell a function call which won’t modify a variable from one which probably will:
  int i;
  f(i); /* i is unchanged */
  g(&i); /* i is likely changed */

However, for composite types, you often want to avoid making a copy when you’re not modifying the variable, so you end up with a function h(const T*) which is called as h(&x) anyway.

C++ adds call-by-reference, so that a call which looks like f(i) no longer tells you that i isn’t modified. This is a shame. Some style rules will give you the benefit of being able to tell modifying from non-modifying functions, while still getting the copy avoidance without burdening the caller with that implementation detail:
  f(T x) /* Call by value: x is a local copy. Use this when you want to play with x's value in f() without affecting the caller. */
  f(const T x) /* Call by value: x is a local copy and const. Use this for easily copied types which f() will only be reading. */

  f(T& x) /* Call by reference: x is shared with the caller and modifyable. Avoid this. */
  f(const T& x) /* Call by reference: x is shared with the caller but not modifyable. Use this for composite types which you don't want to gratuitously copy. Because x is const to f(), the caller can pretty much treat it as if f() got a copy. (The gotcha is that f() has to be aware that it'll see modifications to x made through other references, unlike with a copy.) */
  f(T* x) /* Call by pointer: Use when you want to have f() modify *x for the caller. */
  f(const T* x) /* Call by pointer, but not modifyable through it. Avoid without good casue, as this is generally semantically a call-by-reference. */

With the f(T&) case gone, we once again can be confident that f(i) won’t change i but g(&i) is likely to. More likely than with the C rules even, because we prefer f(const T&) to f(const T*) in cases where we’re merely using pointers to avoid an expensive copy. Pretty nice. Now I just need wide adoption and lint enforcement.

Powered by WordPress