in reply to Re: Win32: Setting a layer with binmode causes problem with close() on Windows (PerlIO silently fails to close the file) in thread Win32: Setting a layer with binmode causes problem with close() on Windows
Good analysis, but I think you have it wrong in one point: At the time when the unlink fails, no other processes are running which have a hold on the file: The one which had created the file is not running anymore (since system waits for the child process to finish), and - just for completion - the process deleting the file has not started yet.
BTW, Both system calls don't exist in my original code in this way (in my application, the file is created on a Unix host asynchroniously, and read and deleted from the Windows process). I have introduced them in the example for the following reason:
- I wanted to create the file by a separate process, to make sure that my Perl program "has not seen" this file before, to make the situation more similar to my original application.
- After the unlink fails, I added an explicit cmd /c del..., because the error message was then clearer than what was stored on $!. In hindsight, I probably could have output $^E instead
--
Ronald Fischer <ynnor@mm.st>
Re^3: Win32: Setting a layer with binmode causes problem with close() on Windows (PerlIO silently fails to close the file)
by BrowserUk (Patriarch) on Jun 17, 2013 at 11:55 UTC
|
I think you have it wrong in one point: At the time when the unlink fails, no other processes are running which have a hold on the file:
Here's the problem. You know the way you have to fork twice under *nix in order to deamonise a process -- the first fork inherits loads of handles (stdin, stdout, stderr etc.) from its parent; so you then close them and fork again to get a process that true independent of its parent -- well similar things can happen under windows.
system starts a new process that inherits lots of stuff from it parent. When it dies, if the parent is still around, many of those shared (duped) handles have to be retained within the kernel -- waiting for all their duplicates to be marked for delete -- and despite that the process has been removed from the system scheduler, those retained, open, shared handles will still be attributed to that now defunct process. So, the fact that system has returned does not mean all of it resources have been cleaned up.
My simplified version of the test script simply removes all of those possibilities and demonstrates that the only process that could have a handle to the file is the perl process itself. Which is then verified using an external tool (handle.exe).
Thus it is the close that is failing silently.
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] |
|
| [reply] [d/l] |
|
I didn't think about this issue! But this would mean that it is unsafe to have an (external) process create a file, and then use it in my program - at least under Windows, which is very picky about this kind of stuff?
Here's the thing. If you want to delete a file that you've been accessing, from the script you've been accessing it from, you need close it first. If you've also run some commands via system that accessed that file, and they have left open, duped handles in the kernel, they will disappear as soon as you close your handle.
So normally, the problem does not arise. Indeed you can verify this by running your OP code with the binmode commented out.
It was only necessary to remove all the subprocesses from your example in order to confirm, by dint of 'it couldn't be anything else', that is was the perl process that was holding the open handle.
It then becomes clear that the "other process" is actually 'this process'; and thus the close is failing silently when binmode has added the ':unix' IO layer to the stack.
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] |
|
sub system_detached {
my $program;
my @args ;
my $cmdline;
if( @_ > 1 ){
( $program ) = @_;
$cmdline = Win32::ShellQuote::quote_system_string( @_ );
} else {
( $cmdline ) = @_;
}
$!=$^E=0;
my $ProcessObj;
## http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=
+vs.85).aspx# CreateProcess function (Windows)
## http://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=
+vs.85).aspx# Process Creation Flags (Windows)
use Win32::ShellQuote();
use Win32::Process();
Win32::Process::Create(
$ProcessObj,
$program,
$cmdline,
0, # don't inherit handles
Win32::Process::DETACHED_PROCESS(),
".", #cwd
) or do {
my $err = int($!).' '.$!." #### ".int($^E)." $^E ";
warn "??CreateProcess failed (\$ProcessObj $ProcessObj) $err "
+;
return;
};
return $ProcessObj;
}
| [reply] [d/l] |
|
|
|
|
|