Monthly Archives: March 2010

Bug of Legend

So. Those of you who notice the things I post will presumably notice I haven’t blogged as much recently. Essentially it’s because I have less time for development between school and work (I’m on shore duty so I don’t deploy, but I’m in charge of a division so my hours are still substantial).

The spare time I have had over the past month I’ve mostly spent trying to (re) fix my new favorite bug ever, bug 182026 which is a crash bug in KPixmapCache::discard().

You should hopefully have no clue about what KPixmapCache is other than that it’s what’s crashing most of your favorite apps, so I’ll give you the rundown. Back when KDE 4 was being developed and we were shifting to use the shiny SVG icons and graphics everywhere it was noticed that rendering SVG graphics took rather more time than simply loading a PNG from disk. So, instead of loading a SVG file from disk every single time it was needed, the end result (a PNG) was cached to disk instead, and a quick check is done to ensure that the underlying SVG file didn’t change. I didn’t write the code but thought it was interesting and committed a couple of bug fixes and now I apparently maintain it. =D

For efficiency reasons that on-disk cache is accessed by each KDE process using a shared memory segment (although it then gets inefficient again by using I/O operations anyways, but that’s for later). Anytime you have multiple processes or threads accessing a shared resource you need a way to handle that contention to make sure that the sensitive parts of the code are only being run by one thread at a time.

The second problem that was reported as 182026 was that the “discard” feature of the cache seemed to cause crashes for a lot of people. (Although oddly enough, not for any of the 3 test systems I have. Call me lucky…). The idea of discarding the cache contents is that the application code knows that something changed which means that essentially all of the stored graphics will not be needed. The major way most people see this is by changing Plasma themes (where the old theme’s graphics are now useless) or by changing the icon theme.

The underlying issue is that ::discard() uses essentially no locking. Instead it tells the shared caches to reload themselves on their next operation (a process referred to as “invalidation”), disconnects from shared memory, and deletes the cache file on disk. Or at least, it used to. Merely adding locking helps, but is solving the wrong problem. Any time the cache is disconnected from shared memory, it will try to reconnect later, re-creating the file on disk if necessary (and it is necessary in this case). But this is all just to say that the cache is now empty, there’s no underlying reason that we have to deallocate everything just to turn around and reallocate it.

So when I committed my fix for 182026, I did the following:

  • I added a flag to the cache to mark if it was simply empty or not. This allows me to discard the cache without having to disconnect it from shared memory or invalidate it.
  • Made KPixmapCache::discard() take the cache lock first before it did any of that.
  • When copying the cache for resizing, KSaveFile is used instead of truncating the cache (especially in case any cache locks have to be broken due to timeouts)

Unfortunately my initial fix had the side effect of breaking the “cache” part of KPixmapCache as it would never find cached items again. It was noticed by a KDE Games developer though so 4.4.2 should still be good to go now that I’ve fixed that.

A final side note is that I think I need to change the code that deletes an entire named cache to discard the cache as well for those processes that already have it attached to shared memory.

I have an alternative shared-memory cache implementation which I hope to integrate for KDE Platform 4.5 or 4.6 (although it may simply end up as KSharedCache or similar instead of merely replacing KPixmapCache due to API additions in KPixmapCache I don’t feel like supporting). At some point in between I may write a post about the underlying cache architecture and some “Do”s and “Don’t”s but I think I’ll just stop here for now. :P

Window button ordering

Sometimes you can’t please everybody. The blog article I linked to argues that the window button ordering change in the alpha releases of the next Ubuntu should be reverted back.

Update: I’ve seen reports that Canonical may have switched the button order back in the latest builds. The last entry I saw on Planet Ubuntu leads me to believe it’s still switched, but my Google-fu is too poor to find something conclusive. (Scarily enough, this very blog is already on the first page of the Google results…)

I agree with the comments about it being hard to get used to since I use a non-default window button order too, after being inspired by Aaron Seigo. My own personal layout is like this:

↓ ↑ < ---- window title ---- > ×

In case it’s unclear, starting from the left I have the minimize button, maximize button, the window title, and then on the right I have the close button.

The reason I have it like this is that I always use the minimize and close buttons, so they need to have the corners to be easiest to find. In particular, the close button just has to be in the upper right, it’s just a reflex for me and I have no particular need to fight it.

It would be annoying when I use Windows to find minimize, except that I normally just use a keyboard shortcut. (I later added a global keyboard shortcut for KWin to do the same thing). Other than that I like it a lot.

I can see why most people would not want the window order changed on them all of a sudden though. Probably the easiest thing would be to allow people to choose their own button order. I know we support it in KWin, given the blog article stating special theme support would be needed in ubuntu, I get the impression that Compiz and/or Metacity do not. :-/ Failing that, I think it’s a bad idea to deviate from the upstream GNOME window manager’s button ordering. Themes were already mentioned as being incompatible so it makes me wonder what else might be.