Gnash makes me gnash my teeth in frustration

A new release of Gnash has arrived: 0.8.9. I like the idea of having an open-source Flash plugin, but Gnash has never quite managed to fill my needs; I was thinking with the new version, things might be a bit better. Alas, after compiling and installing Gnash 0.8.9, all I see are grey rectangles where flash movies should be. This is worse than the previous version! At least with 0.8.8 some flash movies did work.

When starting firefox from the terminal, I see this error output:

Error: Support for renderer agg was not build

“agg” refers to the antigrain renderer, which I indeed I *hadn’t* built. However, one would assume that if there is an option not to build a renderer, then that renderer is indeed optional to the operation of the software. Delving into the source, I discovered that the “agg” renderer was being set as the default at an early stage (in the command line options parsing, which is done via the boost library’s “program_options” module), and because it was then considered set, the setting in the configuration file was not being used, nor was the logic normally used to choose a sensible default coming into play.

So, an easy fix, but it does appear that the release was severely under-tested.

Having now gotten the Gnash plug-in working, I can report that it seems to play youtube videos quite well, but still fails on some flash websites. Hopefully further progress will come soon!

Edit: bug filed.

Advertisements

X keyboard crap

I’m getting this in my log when I try to start X:

[  7780.894] (EE) Error compiling keymap (server-0)
[  7780.894] (EE) XKB: Couldn’t compile keymap
[  7780.894] XKB: Failed to compile keymap
[  7780.894] Keyboard initialization failed. This could be a missing or incorrect setup of xkeyboard-config.
[  7780.894]
Fatal server error:
[  7780.894] Failed to activate core devices.

What’s going on? “Couldn’t compile keymap” has to be one of the most useless error messages ever. Why can’t you compile the keymap??!

Update:

I renamed the “xkbcomp” executable and replaced it with a script which logged options and output before executing the original. I’m seeing this output:

The XKEYBOARD keymap compiler (xkbcomp) reports:
> Error:            Cannot open “/tmp/server-0.xkm” to write keyboard descriptio
>                   Exiting

… However, I don’t understand why it’s unable to create a file in /tmp. I’ve verified the file doesn’t already exist before xkbcomp is run, and that all users can create files in /tmp (the “t” bit is set).

Once again, the error message is bad: please tell my why you can’t open the file. (Hint: it’s called perror).

Update: (Solved!):

Turns out the permissions were the problem. They were:  rwxr-xrwt, i.e. the group was denied write permission. I didn’t think this was a problem seeing as “other” users are allowed to write files, but apparently that’s not how Linux permission checking works.

Trac is super crap

A couple of projects I work on use Trac (0.12.1, the latest at time of writing) for bug/issue tracking. I recently got an email from a user of our Trac system, saying that she couldn’t seem to reset her password – that is, the system told her that it had reset her password and sent her an email with the new password, but in fact the email with the new password never arrived.

I went to scan the trac logs, but it turns out they were disabled by default (first problem). I enabled the logs and reset my own password, but no joy – nothing untoward appears in the logs. I checked and double-checked the mail settings, but they all looked ok. I then altered the configuration, switching from SMTP to sendmail and specifying a freshly-crafted wrapper script which logs when it’s called as the “sendmail” executable. With this I can verify that the mail is not sent – the script doesn’t appear to be being executed, and the mail server logs show no activity.

Finally I stumble on another setting:

acct_mgr.notification.accountchangelistener = enabled

And with this, finally, finally, Trac starts sending the new password emails when I do a password reset. Now, this is a documented setting, but really, I mean really, couldn’t there have been some warning in the logs? Or could maybe the setting to allow users to reset their password also enable the “account change listener” (whatever that is)? Is it too much to ask that an obviously broken configuration be either made redundant or at least identified as such by the software?

Well, I’ve solved the original problem. It’s at this point, though, that I realise a much more significant problem exists: The Trac AccountManagerPlugin password reset functionality allows anyone to reset anyone else’s password, and, get this, this is where it gets good, they can have the new password sent to any email address. [Update: no, this is wrong; once you actually enable the acountchangelistener setting as described above, you get an error if the specified email address doesn’t match the account. However, if you don’t enable that setting, then anyone can reset your password; however they won’t receive the new password at the email address they specify].

When the password reset functionality is enabled, if you register as a new Trac user you will see text telling you that providing your email address is optional, but if you do provide it you will be able to “reset your password if you ever forget it”. That’s clearly bollocks [if accountmanagerlistener isn’t enabled], since the password reset function doesn’t verify that the email address is correct for the user [in that case].

The real problem, I guess, is that Trac doesn’t provide any decent built-in account management. I mean, should the account manager – a most basic piece of functionality – really be a plugin? I don’t think so. (Worse than that, to use the plugin with Trac 0.12, you have to use a subversion pull of the plugin rather than a released version!).

And that is why Trac is super crap.

Php 5.3.3

When running “./configure –help” for PHP 5.3.3, one of the output lines is:

–without-sqlite3[=DIR] Do not include SQLite3 support. DIR is the prefix to
SQLite3 installation directory.

… which cracks me up. I need to specify the installation directory of SQLite3, in order to not include support for it in my PHP build?!!

Update 22/9/2010: I couldn’t manage to get php-5.3.3 to build on a Solaris system. I’m now trying 5.1.5; I’ve got this to build but for some reason it doesn’t build the cgi support even though I’ve specified “–with-cgi” on the configure command line. Googling reveals that maybe I need to disable Apache support for this, which lead to this equally daft configure output:

./configure –without-apache –without-apxs –with-mysql=/usr/local/mysql –with-gnu-ld –enable-cgi –enable-fastcgi
loading cache ./config.cache
checking for Cygwin environment… (cached) no
checking for mingw32 environment… (cached) no
checking for egrep… (cached) egrep
checking for a sed that does not truncate output… (cached) /usr/bin/sed
checking host system type… sparc-sun-solaris2.9
checking target system type… sparc-sun-solaris2.9
configure: error: –with-apache and –with-apxs cannot be used together

I mean, seriously… I specified without apache and without apxs, and it tells me that I can’t use the “with” options together??!!

Gnash 0.8.8 – still crap, but slightly less so.

Gnash 0.8.8 was recently released, with claims of “full youtube support”, so I gave it a spin. I immediately hit this build error:

make[4]: Entering directory `/usr/src/gnash-0.8.8/gui' CXXLD  gtk-gnash../librender/.libs/libgnashrender.so: undefined reference to `gnash::rgba::set_lerp(gnash::rgba const&, gnash::rgba const&, float)'collect2: ld returned 1 exit statusmake[4]: *** [gtk-gnash] Error 1make[4]: Leaving directory `/usr/src/gnash-0.8.8/gui'

Odd… the symbol is defined, it’s in libgnashcore.so, and the link does link against that library. Turns out the culprit is the “–enable-visibility” argument to configure. That’s right – Gnash fails to build if you enable enhanced symbol visibility support (because it makes a symbol non-visible). What a joke.

Speaking of configuring Gnash, what exactly is this:

WARNING: The BOOST serialization library is recommended! Install it from http://www.boost.org or .deb users: apt-get install libboost-serialization-dev Gnash will compile anyway, but not all tests will work.

… meant to mean?? Does the library actually add functionality, or is it just needed for a few tests?

Anyway, I eventually got it working, and I’m pleased to report that it does play Youtube videos as advertised (not always perfectly, but it’s good enough). It still doesn’t handle a few other flash applets that I’m aware of, however, including this blog’s access statistics graph.

Update 15/09/2010: In a strange twist, WordPress have upgraded their graph software and Gnash seems to run the new version reasonably well.

Update 25/09/2010: On closer inspection, the new WordPress graphing software doesn’t use Flash, and that’s why it runs perfectly.

Lies, damned lies, and Rails documentation

I was recently playing with Rails again. A while back a site I was working on had an issue where the parameters from an uploaded form were all coming in as file objects – even the parts that didn’t correspond to uploaded files. The client in this case was some Java software using the Apache Httpclient library. We’d only recently upgraded Rails, and it turned out we were seeing the problem described here:

http://blogs.sun.com/mandy/entry/rack_and_content_type_fo

The problem was easily worked around. This led me on a hunt, however, for some documentation on how exactly you are meant to handle form uploads in Rails. About the only vaguely official-looking documentation I can find at this point is the Action Controller Overview guide, which has this to say:

Note that parameter values are always strings; Rails makes no attempt to guess or cast the type

Clearly baloney. If one of the form parts is a file upload, then what you get is an object with several methods defined including “read” to return the contents of the file as a string, as well as things like “original_filename” which tell you the filename as specified by the uploader. None of this is documented anywhere.

It’s this “we don’t need to document it” attitude that really annoys me about Rails. Sure, there’s all this magical stuff you can do with it and it has all these built-in goodies that can save you hours of coding just by using magic variable names (except for those times of course when you have to spend hours debugging, because you used one of those magic variable names by mistake and without realising). But there’s just no reliability with the API. The params hash for instance – what exactly am I allowed to do with a value I pull from the hash? Can I be sure that it will either be a string or one of these mysterious file upload objects? This isn’t the only omission in the documentation; for instance what does the “session” method in ActionController::Request actually return? What am I allowed to call on it?

This is the real strength of languages with strong typing – programs written in them are, to a certain degree, self-documenting. If I know what type a method actually returns then I know for certain what methods I can call. No nasty surprises when the framework developers suddenly decide to make it return a different kind of object!

Edit 27/8/2010: Another major strength of statically-typed languages that I forgot to mention is of course the ability to refactor code with the assistance of automated tools. As discussed in this blog post by Cedric (and I love the title).

FUSE, and ways in which it sucks.

I’ve just started toying around with Fuse. The possibilities of writing comprehensive filesystems in user space interests me, not the least because it makes development much easier before you move to kernel space.

I’ll say it right out, Fuse is certainly not the worst conceived / designed/ implemented piece of software by a long shot. The documentation isn’t great, but it’s not totally lacking either (which immediately puts Fuse a cut above a whole swathe of other open source projects). It’s not perfect however.

My main annoyance is the multi-threading support which, frankly, shouldn’t exist; i.e., it should be handled by the application and not the library. It is, generally, better when software layers are thin; it should be up to the app to do appropriate locking etc., and the library (in this case Fuse) should just specify in the documentation where the locking is needed (or rather, more usefully, where it is not needed). Ok, quibbles, and providing more functionality is hardly a crime; after all, the low-level layer is still available and (mostly) unobfuscated by the higher-level functionality.

The real issue is that linking against libfuse pulls in the pthread shared library as well, which is not so good. The pthread library incurs overhead (other than taking up memory/address space) because when it is loaded, locking and unlocking mutexes suddenly become real operations – which means fputc() and a whole bunch of other library functions become a weeny bit slower. (Don’t believe me? do “nm” on /lib/libc.so and /lib/libpthread.so and notice that they both define pthread_mutex_lock).  Fuse should really be split into two librarys, libfuse and libfuse_mt, and only the latter should require pthreads. (Or, as I suggested earlier, just ditch the multi-thread functionality altogether, leave it up to the application to pull in pthreads if it really needs it).

Another annoyance is the fuse_chan_receive function:

int fuse_chan_recv(struct fuse_chan **ch, char *buf, size_t size);

Notice that first argument? Not just a pointer, it’s a pointer-to-a-pointer. Why, great Zeus, why??! The function is meant to receive data from a channel, in what crazy circumstance would you want it to change the channel pointer itself to point at something else? And in fact, the function delegates to a another function via a pointer (embedded in **ch) to a fuse_chan_ops structure; in the library itself, as far as I can see, there are only two implementations (one to receive directly from the kernel, and another called mt_chan_receive) and neither of them does actually alter the value of *ch. If you have a look at the implementation of fuse_loop() though you’ll notice the author clearly had the possibility in mind, since he copies the channel into a temporary pointer variable (tmpch) before using fuse_chan_recv – so yes, the bad API design has caused increased code complexity.

The comments above the declaration of fuse_chan_recv don’t give any clue as to why it would ever modify the *ch value and incidentally ch is incorrectly documented as being a “pointer to the channel” when it is of course really a “pointer to a pointer to the channel”.

Oh, and the mt_chan_recieve function I mentioned earlier – well, it presumably has something to do with the multi-threading support, but it’s hard to be sure because the function lacks anything bearing the slightest resemblance to a comment, and there certainly isn’t any other explanation of what it does nor how it works.