2006-10-09 Oddmuse Race Conditions

I kept thinking about a report I had heard from some Hungarian users. Something about them loosing permanent anchors. Weird. Today I figured out what the problem was while walking to the train station: A race condition! Data is read from the filesystem into memory. Stuff happens. When appropriate, a lock is created, and data is written back to the filesystem. The problem is not the writing. The problem is the time window between the reading and the writing.

A reads data. B reads data. A modifies data and writes it to disk. B modifies data and writes it to disk. → A’s changes are lost!

It turns out that I had two such instances. One of them was self-correcting: The creation of the page index file can go wrong, but it’ll fix itself when the next new page is created. But the permanent anchors file is brittle. It’s not easy to regenerate. That sucks. I knew that such a file was a bad idea. Damn.

Now that I think of it, clearing the cache will break all links to permanent anchors until you have visited all the pages where permanent anchors are defined. Gah!

I’ll fix the easy stuff first: The race conditions, and the new init code.

Time passes.

Hours, in fact.

Finally!

All tests successful, 42 subtests skipped.

Files=56, Tests=1148, 666 wallclock secs (418.29 cusr + 78.43 csys = 496.72 CPU)

​#Oddmuse

Comments

(Please contact me if you want to remove your comment.)

So were you able to remove the race condition, or just minimize the time window?

– AaronHawley 2006-10-10 03:12 UTC

AaronHawley

---

omg, 666 seconds O.o

– TheSheep 2006-10-10 09:04 UTC

TheSheep

---

I think I was able to remove the race conditions. For example when caching the list of pages available on the system I now request the lock before I even start looking for the files:

my $locked = RequestLockDir(’index’, undef, undef, -f $IndexFile); foreach (glob(”$PageDir/_.pg $PageDir_*..pg”)) # = 1; } WriteStringToFile($IndexFile, join(’ ’, %IndexHash)) if $locked; ReleaseLockDir(’index’) if $locked;*

Before the change, only WriteStringToFile was wrapped in a lock.

Or when updating permanent anchors, I force a read using PermanentAnchorsInit:

} elsif ($PermanentAnchors$id} = $OpenPageName; WritePermanentAnchors(); ReleaseLockDir(’permanentanchors’);

I haven’t installed it yet, however.

– Alex Schroeder 2006-10-10 10:32 UTC

Alex Schroeder