For discussion/bugtracking about the extension.

Hi Y!!,

I’ve downloaded your EMutex extension, and I have a question on how it works. Really, I didn’t notice any problem, that’s just I would like to understand better the basic principles of your mutex.

I’m probable wrong but it seems to me that in a particular case, 2 php threads could get the same mutex.

On the lock method, you wrote :

file_put_contents($path, serialize(array($timeout, time())), LOCK_EX);

This is the only command that is garanteed to be atomic right ? Then, 2 php threads could execute all previous lines, and reach this one sequencially … isn’t it ?

Thread 1> if (false !== $data && (0 === $data[0] || $data[0] + $data[1] > time()))

Thread 2> if (false !== $data && (0 === $data[0] || $data[0] + $data[1] > time()))

Thread 2 > array_push($this->_locks, $id);

Thread 1 > array_push($this->_locks, $id);

Thread 1 > file_put_contents($path, serialize(array($timeout, time())), LOCK_EX);

Thread 2 > file_put_contents($path, serialize(array($timeout, time())), LOCK_EX);

// both thread have the mutex !!

Of course, that is very bad luck, but from a formal point of view, this is possible no ?

Please, could you tell me if and why I’m wrong …



Hehe good find. Yes I think it’s possible. Though, under some crazy circumstances since the time-difference between checking and writing the lock file is probably under 3ms. I’m not really sure yet what a good fix would be, probably the use of flock() with only one global lock file (that hold’s all locks in a serialized array)?

I updated the extension.

  • All locks in one file

  • Now using microtime() for more precise timeout

  • Some other enhancements

that it greay Y!! … As I told you, I never had any problem with EMutex, my question was just theorical, but I apreciate you new enhancments and this time, it seems that there can’t be any Mutex ‘collision’ …even theorically ;)




That’s an awesoem extension, exactly what I was looking for. Thx!

Following a profile, it turned out that the file locking process took 500ms in total in my process (lock/unlock -> 2x250ms).

So I looked for an alternatived method.

The first alternative method is to use the ‘mysql’ GET_LOCK and RELEASE_LOCK functions. This works only when you get one lock in an application instance, but that is good enough for me.

The updated extension is attached.

Further methods could be using the database (and a specific table), or the cache (especially if it is a CDbCache).