This is the file test1.php:
<?php
set_time_limit(0);
for($i= 1;$i<5000 ;$i++){
$comm_sjis = "echo 'test'";
$result = exec($comm_sjis);
}
unset($result);
echo 'ok';
This is file test2.php:
<?php
set_time_limit(0);
function write_txt($str)
{
$filepath = 'E:/temp/test.xml';
if (($fp = @fopen($filepath, "a")) === false) {
return;
}
if (!flock($fp, LOCK_EX)) {
@fclose($fp);
return;
}
if (fwrite($fp, $str . "\n") === false) {
@flock($fp, LOCK_UN);
@fclose($fp);
return;
}
if (!fflush($fp)) {
@flock($fp, LOCK_UN);
@fclose($fp);
return;
}
if (!flock($fp, LOCK_UN)) {
@fclose($fp);
return;
}
if (!fclose($fp)) {
return;
}
}
for($i= 1;$i<100 ;$i++){
write_txt('test');
unlink('E:/temp/test.xml');
}
echo 'ok';
If I run file test2.php while test1.php is running, an error will occur:
Warning: unlink(E:/temp/test.xml): Permission denied in C:\xampp\htdocs\test2.php on line 45
When I only run test2.php, without test1.php, this error does not occur. Why does unlink give a Permission denied error when I execute the function?
I'm using XAMPP 3.2 vs php 5.6 with Windows 7.
You're silencing errors in fopen
which means that if, at any point, the file fails to open (perhaps because of a memory limit being reached in XAMPP, for example), you'd have no way of knowing in your script (you can view it in your logs).
From the PHP Manual:
bool unlink ( string $filename [, resource $context ] )
Deletes filename. Similar to the Unix C unlink() function. An E_WARNING level error will be generated on failure.
unlink
deletes a file. That means that if your file fails to open using fopen
, and you haven't created it already, it may well not exist. Trying to unlink
a file that does not exist will result in an error.
An easy solution would be to silence errors on unlink
as well.
@unlink('E:/temp/test.xml');
That way it will fail gracefully if your function fails to write a file. Another option is to check if the file exists before trying to unlink.
$file = 'E:/temp/test.xml';
if (file_exists($file)) {
error_log(‘could not write file’);
unlink($file);
}
My favored option in this case might be to use Exceptions
. When you fail to open or fail to unlock a file, throw an Exception
. You can catch it, log the issue and break the loop before you try to unlink
.
That should help you debug what is going on.
Example: namespace Test;
class FileException extends \Exception { }
class UnlockFailedException extends FileException { }
function write_txt($str)
{
$filepath = 'E:/temp/test.xml';
if (($fp = @fopen($filepath, "a")) === false) {
throw new FileException('Could not open file');
}
if (!flock($fp, LOCK_EX)) {
@fclose($fp);
return;
}
if (fwrite($fp, $str . "\n") === false) {
@flock($fp, LOCK_UN);
@fclose($fp);
return;
}
if (!fflush($fp)) {
@flock($fp, LOCK_UN);
@fclose($fp);
return;
}
if (!flock($fp, LOCK_UN)) {
@fclose($fp);
throw new UnlockFailedException('Unable to unlock file.');
}
/**
* This doesn't do anything
* if (!fclose($fp)) {
* return;
* }
*/
fclose($fp);
}
Then:
$msg = 'ok';
for($i= 1;$i<100 ;$i++){
try {
write_txt('test');
unlink('E:/temp/test.xml');
} catch (FileException $e) {
error_log($e->getMessage());
$msg = 'errors detected';
}
}
echo $msg;
By adding exception handling, you can debug this kind of behavior for yourself and find the root cause of the issue.
A couple final notes:
I run Linux, so it’s not easy for me to test this behavior on a Windows 7 XAMPP machine. However, I suspect it is because the system is locking due to limited I/O resources. Note that, according to the manual, Windows places a madatory lock on the file (whereas in Linux the lock is advisory). Running flock
in a massive loop and echo
in a massive loop on a limited resources system can lead to resources failing. If you intend to run something like this in production you won’t run into it as often but you will still need to account for it. Exception handling and error logging can ensure that when the file doesn't work you will have enough data to debug.
Assuming unlink
is the problem is not a safe assumption at all.
As stated, silencing unlink or checking to see if the file exists will silence this error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With