1

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';
    }

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

2 Comments

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.
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.
1

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.

2 Comments

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?
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.
0

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.

1 Comment

The check for file existance and lock file creation is at least two commands, which means that it is still possible to have race conditions. flock doesn't exist for no reason.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.