tags:

views:

29

answers:

3

I am trying to stop my cron script from allowing it to run in parallel. I need it so that if there is no current execution of it, the script will be allowed to run until it is complete, the script timesout or an exception occurs.

I have been trying to use the PHP flock function to engage a file lock, run the script and then release the lock. However, it still looks like I am able to run the script multiple times in parallel. Am I missing something?

Btw, I am developing on Mac OS X with the Mac filesystem, maybe this is the reason the file locks are being ignored? Though the PHP documentation only looks about NTFS filesystems?

        // Construct cron lock file path
    $cronLockFilePath = realpath(APPLICATION_PATH . '/locks/cron');

    // Get cron lock file
    $cronLockFile = fopen($cronLockFilePath, 'r');

    // Lock cron lock file
    if (flock($cronLockFile, LOCK_EX)) {

echo 'lock';
sleep(10);

    } else {

echo 'no lock';
    }
+1  A: 

I think what you could do is write a regular file somewhere (lock.txt or something) when script starts to execute, without any flocks, and remove it when the script stops running. And then always check upon initialization whether that file already exists - another instance running.

jayarjo
+1  A: 

Your idea is basically correct, but tinkering with file locks generally leads to strange behaviour.

Just create a file on script start and delete it in the end. The presense of the file will indicate if the cron is already running. Make absolutely sure, that the file is deleted in the end, even if the cron runs into an error halfway through.

FlorianH
handling errors shouldn't be a issue, i'll just catch all exceptions and then unlink the created file... but i imagine that handling script terminations is not possible, for example server restarts, apache restarts, or script timeouts... since its a cron file, i might just make the script run without a timeout.
cappuccino
You could try to have two scripts: The first one creates the "lock" file, executes your current cron script and then deletes the "lock" file. So even if your current cron script explodes, the first script will still remove the lock.Another thing I already did: if your script detects that the "lock" file is there, but the filectime is older than an hour you go ahead and delete it anyway, because it is very likely that something went wrong.
FlorianH
+1  A: 

From documentation:

Warning

On some operating systems flock() is implemented at the process level. When using a multithreaded server API like ISAPI you may not be able to rely on flock() to protect files against other PHP scripts running in parallel threads of the same server instance!

You can try to create and delete file, or write something in to it.

codez
I see, I see, I've seen some other methods which rely on creating a file and then deleting once complete. however, this wont be able to handle script timeouts and exceptions where the script is terminated before the execution of the unlink function. As such though a script might have been terminated, the script will not be able to run again since the created file has not been delete. Is there a method to deal with this situation?
cappuccino
First that comes in mind, maybe you can try to open socket and when other threads tries to open same socket on same port they fail.
codez