NSDistributedLock documentation claims lockDate returns nil if the lock does not exist, but in fact it returns a date of 2001-01-01 00:00:00 +0000. This simple code can test it:
NSDistributedLock* dlock = [[[NSDistributedLock alloc] initWithPath:@"/tmp/peter-34593459835.lock"] autorelease]; NSLog( @"NSDistributedLock is %@ and lock date is %@", dlock, [dlock lockDate] );
To understand why this is horrendously bad, a reasonable implementation of locking will check lockDate, and if it is old, break the lock with breakLock, either before or after failing to try the lock. This means you will call breakLock when no lock file exists at the time of your call to lockDate, which leaves a humongous race condition hole in your code - not much better than no locking at all.
Consider this code case:
while ( ![lock tryLock] ) { NSDate* locked = [lock lockDate]; if ( locked && [locked timeIntervalSinceNow] < -60 ) [lock breakLock]; usleep( 1000 ); }
If another process has the lock at line 1 and then releases it for line 2, and then acquires it for line 3, you'll assume the lock is very old and break it. This is disastrous and I can see no safe workaround for this terrible behaviour.
Luckily, writing your own version of NSDistributedLock is relatively straight forward.
So if you use NSDistributedLock in your code, verify the behaviour of lockDate, and if you get the same result, look very closely at your lock breaking code to see what race conditions have been left in there by this poor behaviour.
Posted Friday, June 22, 2012. Permalink. 1 Comments.
None yet.
I was in search for this string , I found this very useful for my coding ,
Thanks for Sharing
Posted Monday, October 8, 2012 06:33 AM by leeena.