Under *nix, if two concurrent (Perl) processes have open handles to filea and one of the processes renames fileb over filea, when the second process next reads via it's open handle, does it read
Presuming the second process has an open handle it should still see the original contents. It's similar to how processes with open descriptors can still read the file's contents even after the last link in the filesystem has been unlink'd (i.e. the way you get truly anonymous tmp files). Once that descriptor's closed (and presuming no other hard links to the original filea exist) the blocks for filea would go back on the free list and it's completely inaccessible (unless one really wants to grobble through a raw block device with dd or a filesystem debugger, of course :).
Additionally: it shouldn't matter if it's one of the owners of an open descriptor or not that does the rename call; so long as anyone's got an open descriptor it all should point to the same blocks on disk.
You may view the original node and the consideration vote tally.
The original contents. The original file is held open, nameless, and does not disappear until closed by the last process which held it open. That's why race conditions on file writing are so critical to avoid. A process has no way to know when thay occur without some form of file locking.
Once a process has an open file descriptor, it no longer cares about the name on disk.
After Compline,
Zaxo
It's fairly simple to demonstrate that this is not true...
jasonk@critter% cat foo.pl
#!/usr/bin/perl -w
##################
open(OUT,">/tmp/testfileA");
print OUT "This is testfileA\n";
close(OUT);
open(OUT,">/tmp/testfileB");
print OUT "This is testfileB\n";
close(OUT);
open(IN,"/tmp/testfileA");
system("mv /tmp/testfileB /tmp/testfileA");
print ;
jasonk@critter% ./foo.pl
This is testfileA
| We're not surrounded, we're in a target-rich environment! |
|---|
I suppose that the rename is just changing the directory entry. I believe that a /bin/cp will give the exact semantics that I supposed earlier? Maybe someone will check for me.
Or maybe I'll just get downvoted.
,welchavw
-> Code should look like this
$ cat foo.pl
#!/usr/bin/perl -w
##################
open(OUT,">testfileA");
print OUT "This is testfileA\n";
close(OUT);
open(OUT,">testfileB");
print OUT "This is testfileB\n";
close(OUT);
open(IN,"/tmp/testfileA");
rename ("testfileB", "testfileA");
print ;
close IN;
$ ./foo.pl readline() on closed filehandle IN at ./foo.pl line 15.So the answer is "neither - rename closes the filehandle". I.
So the answer is "neither - rename closes the filehandle".
I think you missed the bit about "... two concurrent (Perl) processes ..." and "... when the second process next reads via it's open handle ..."
A better test would be
#!/usr/bin/perl use strict; use warnings; open OUT, '>', 'junk.1' or die $!; print OUT 'X'x 20 . "$_\n" for 1 .. 20; close OUT; open OUT, '>', 'junk.2' or die $!; print OUT 'Y'x 20 . "$_\n" for 1 .. 20; close OUT; open IO, '+<', 'junk.1' or die $!; seek IO, 0, 0; print scalar; system $^X, '-le', q[ print rename( 'junk.2', 'junk.1' ) ? 'worked' : 'failed']; print scalar ; seek IO, 0, 0; print scalar ; close IO; unlink 'junk.1';
$ echo "hello" > toto $ cat toto hello $ perl -e 'open F, "At the same time I launch in another terminal:'
$ perl -e 'open F, ">toto"; print F 'goodbye'; close F; sleep 30'The output in the first shell is "goodbye". If I change the second one liner to rename the file :
perl -e 'open F, ">toto"; system ("mv toto tata"); print F 'goodbye'; close F; sleep 30'
The output remains goodbye. However, if I change the second one-liner to:
perl -e 'open F, ">toto"; system ("mv toto tata"); print F 'goodbye'; sleep 30'
So to close the file last, then the first oneliner reads nothing at all.
perlmonks.org content © perlmonks.org and Anonymous Monk, BrowserUk, Fletch, ioannis, jasonk, lidden, NodeReaper, wazoox, welchavw, Zaxo
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03