1

Error deleting file if there are multiple connections to multiple page. Error:Warning: unlink(folder/1.txt.txt) [function.unlink]: Permission denied in C:\htdocs\fopen.php on line 7

Note: If only one connection to access everything normally occurs (no error occurs).

PHP code fopen.php:

<?php
function fastWrite($a){
    echo 'Coping file: "',$a,'" to "',$a,'.txt"<br>';
    copy($a,$a.'.txt');

    echo 'Delete file: "',$a,'.txt"<br>';
    unlink($a.'.txt');
}

for($i=0;$i<10;$i++){
    fastWrite('folder/1.txt');
    echo '<hr>';
}
?>

html/javascript code (to simulate multiple connections):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
<title>my test</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript">
function myTest(z){
    $.ajax("fopen.php?time="+(new Date().getTime()),{"success":function(data){
        $("<div></div>").addClass("sty").html(data).appendTo("body");
    },"error":function(a,b,c){
        $("<div></div>").addClass("sty").html([a,b,c]).appendTo("body");
    }});
}
</script>
<style>
.sty{
border:1px #000 solid;
overflow:auto;
margin:5px 0 0 5px;
}
</style>
</head>
<body>
<p><a href="teste.html">New test</a></p>
<script type="text/javascript">
var dd = "";
for(var i=0;i<10;i++){
    dd += "myTest(\"#a"+(i+1)+"\");\n";
}
eval(dd);
</script>
</body>
</html>

What did I do wrong?

Thanks.


Solution: clearstatcache

19
  • make sure, the file is not being used by other processes Commented Nov 10, 2012 at 16:58
  • This is obviously race conditions. What the problem? Commented Nov 10, 2012 at 17:00
  • There is, why would not fail when there is only one connection. When there's just no connection errors occurs. Help me please. Commented Nov 10, 2012 at 17:00
  • @nikita2206 Test the code if you can, the following error occurs: Warning: unlink(folder/1.txt.txt) [function.unlink]: Permission denied in C:\htdocs\fopen.php on line 7 . This error does not occur when there is only one connection Commented Nov 10, 2012 at 17:02
  • please, be clear. what are you doing with file and why do you want to delete? describe the situation more explicitly. what connections do you mean? Commented Nov 10, 2012 at 17:03

2 Answers 2

3

You're having a problem because two processes are trying to copy and delete the same file at the same time. Because they are separate processes, you can't easily control the order in which they do things.

Imagine two processes, running fastWrite() at the same time:

  • t1 copies 'a' to 'a.txt'
  • t2 copies 'a' to 'a.txt'
  • t2 deletes 'a.txt'
  • t1 tries to delete 'a.txt', but fails because it does not exist

This is called a "race condition".

If you don't mind that the unlink call will sometimes fail, you can ignore the error by using the '@' symbol in front of the command:

@unlink("$a.txt");

I'm pretty sure that saving user-generated data into the same file over and over again isn't your ultimate goal. You obviously encountered this problem in the pursuit of something larger. Maybe you should start a new question more focused on that problem.

If you just need a temporary file to work with during the connection, don't always name the file the same. Instead, you could:

function doStuffToFile($fname) {
    $tempName = $fname . "." . getmypid() . "." . rand();
    copy($fname, $tempName);
    // do stuff to your temporary file
    unlink($tempName);
}
Sign up to request clarification or add additional context in comments.

7 Comments

Nah, it wouldn't be "perm denied" then. It's happening when one copies and another tries to delete.
Instead of @, would not verify that the process is open? I tried is_readable and is_writable but still the same error occurring.
between is_writable() and unlink(), another process can still delete the file. @nikita2206 may have a point about permissions. What OS are you using, and what are the permissions of the files you are creating?
After copying the file, you should try chmod("$a.txt", 0777); and see if you at least get a different error. Your race condition will still exist, but you might get a "file not found" error instead of a permission error.
@slashingweapon tried using CHMODE. The error continues to occur. Like I said the error only occurs with multiple connections/requests to code.
|
1

The problem is that you have two or more scripts that write to and delete 1.txt.txt. This is called a race condition. Script1.php has no direct way of knowing if Script2.php is using a file, you need to implement this mechanism yourself.

A simple solution is to create a lock file before using the shared file and delete the lock file once you are done with it.

There is a new problem then: how do you ensure that the two scripts do not create the lock file at once? Script1.php might find that lock file isn't there but before it actually creates the file, the processor switches to Script2.php which also finds the lock file missing. What then?

PHP provides a useful flock function. I am not aware of the gory details but I believe it should solve your problem, to some extent, on some platforms at least.

<?php
function fastWrite($a)
{
    # //// LOCK \\\\
    $fp = fopen("fastwrite.lock", "w");
    if (flock($fp, LOCK_EX) === false) { # PHP will stop at this line until the lock is acquired
        die("flock failed");
    }
    # \\\\ LOCK ////

    echo 'Coping file: "', $a, '" to "', $a, '.txt"<br>';
    copy($a, $a . '.txt');

    echo 'Delete file: "', $a, '.txt"<br>';
    unlink($a . '.txt');

    # //// UNLOCK \\\\
    if (flock($fp, LOCK_UN) === false) {
        die("flock failed");
    }
    fclose($fp);
    # \\\\ UNLOCK ////

}
for ($i = 0; $i < 10; $i++) {
    fastWrite('1.txt');
    echo '<hr>';
}

PS: I was not able to reproduce the race condition on my system.

1 Comment

Is there a way to acquire a lock on the whole directory and prevent other processes from deleting it, but let them read all the files in the directory?

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.