Jump to content

Why file_exists not working?


peter844

Recommended Posts

Hello!

I'm trying to understand why this script doesn't work, when I execute script simultaneously in same browser or browser tab, second script do not see the created file "/tmp/monkey.tmp" (php7.4-fpm + nginx, default config, opcache enabled) 

As soon as I used two different browsers, it works like expected, if I execute same script/URL simultaneously and one script with random data for example URL?_=monkey, it works like expected, problem is same URL in same browser, I dont understand why

$tmpfile = '/tmp/monkey.tmp';
                
clearstatcache();                                                                             
if(file_exists($tmpfile))
{
	die('file exist');
}
else
{
	file_put_contents($tmpfile, 'blabla');	   
}

sleep(20);

exit;

 

Edited by peter844
Link to comment
Share on other sites

All I see is you are trying to save a bit of text as a file.  What I don't understand is the clearstatcache and the sleep(20).  So what is NOT happening - the file is not created?  How about turning on error checking and see if you get anything?

Link to comment
Share on other sites

2 hours ago, ginerjm said:

All I see is you are trying to save a bit of text as a file.  What I don't understand is the clearstatcache and the sleep(20).  So what is NOT happening - the file is not created?  How about turning on error checking and see if you get anything?

Sleep is for debug, i need to execute scripts simultaneously in same browser, i need first script running when execute second script, clearstatcache clears file status cache, first script run create file and then sleep for 20 seconds, but second simultaneously script run (for example executed 3 seconds later) do not see the created file "/tmp/monkey.tmp"

https://www.php.net/manual/en/function.sleep.php
https://www.php.net/manual/en/function.clearstatcache

 

Edited by peter844
Link to comment
Share on other sites

And the question is why?   Why do you need to post the same file at the same time?  What are you really testing?   I imagine also that the OS will run into a lock situation if you try and write the same file at the same time.   This seems like a fruitless exercise unless you can give us some idea what your goal is.

Link to comment
Share on other sites

10 minutes ago, ginerjm said:

And the question is why?   Why do you need to post the same file at the same time?  What are you really testing?   I imagine also that the OS will run into a lock situation if you try and write the same file at the same time.   This seems like a fruitless exercise unless you can give us some idea what your goal is.

Prevent multiple execution of long running script, sorry, but it's clear from the code, you probably don't understand how the code I pasted here works, nevermind

Edited by peter844
Link to comment
Share on other sites

You control that by doing checking of the events you are trying to prevent from happening I suppose.  What is it in your 'long-running' script that you don't want interference from another instance to occur?   And just what is it that could be so long-running that 2 scripts would actually meet up at?

Link to comment
Share on other sites

OK - if you are worried about multiple users creating and removing the same filename why not use a random filename that only exists for that particular instance of the script?   That way if there is more than one executing at the same time they won't interfere with each other when it comes to that filename usage.

Link to comment
Share on other sites

3 hours ago, ginerjm said:

What is it in your 'long-running' script that you don't want interference from another instance to occur?   And just what is it that could be so long-running that 2 scripts would actually meet up at?

The intent is to essentially create a single instance script, similar to single-instance applications on the desktop.  If you try and launch a second instance, it detects the first instance and either doesn't run or does something different.   One possible scenario for this is if you have some cron job that runs every minute.  If for some reason it takes longer than a minute to run, sometimes it's easier to just prevent the second instance from starting than to write the scripts in such a way that they don't cause problems.

@peter844, assuming that is an accurate description of your goal, file_exists is not really the correct way to solve the problem.  If you actually ran both scripts at the exact same moment, it's possible for them both to pass the file_exists test before either of them has a chance to actually create the file.

A better solution is to use fopen with mode x flag to create the file.  In this mode, fopen will fail if the file already exists, or create the file if it does not.  Your script can use that to determine if the other instance is already running.  Example:

$lockFile = __DIR__.'/monkey.tmp';

$fp = @fopen($lockFile, 'x');
if (!$fp){
	die('Script already running.');
}

register_shutdown_function(function() use ($fp, $lockFile){
	fclose($fp);
	unlink($lockFile);
});

An even better solution, is to use flock to obtain an exclusive lock on the file.  If the lock cannot be obtained then that means there is a script still running holding the lock. Example:

$lockFile = __DIR__.'/monkey.tmp';

$fp = @fopen($lockFile, 'c');
if (!$fp){
	die('Unable to access lock file');
}

if (!flock($fp, LOCK_EX|LOCK_NB)){
	die('Script is already running.');
}

register_shutdown_function(function() use ($fp, $lockFile){
	flock($fp, LOCK_UN);
	fclose($fp);
	unlink($lockFile);
});

 

Link to comment
Share on other sites

@kicken
Thanks for your reply, I know about the possibility of fopen and flock, I have the same problem with PHP semaphore, the problem is caused only by Google Chrome, when I disable the browser cache (in Google Chrome), it works like expected, even if there is no cache headers in the response and even when I insert a no-cache header into the response, when aj insert to response PHP's process ID, pid is not the same, it doesn't make sense for me

another solution
https://www.php.net/manual/en/function.getmypid.php#112782

Edited by peter844
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.