How to automatically delete files created using the :: Temp file when the program stops unexpectedly?

I am creating temporary files with the file :: Temp. My temporary files are automatically deleted when the program terminates normally. I expected this to happen when my program stopped ctrl + c. Is not.

Here is a simple program demonstrating my problem.

The desired behavior is this. How can i achieve this? I am on Linux.

  • temp file is not deleted when closing file descriptor (ok)
  • temp file is deleted when the program exits normally (ok)
  • temp file is deleted when the program exits using ctrl + c (does not work)

.

#!/usr/bin/perl -l use warnings; use strict; use File::Temp qw(tempfile tmpfile); my $fh = File::Temp->new; close $fh; -f "$fh" || die "$fh does not exist"; print "hit enter and the file will be deleted"; print "hit ctrl+c and it won't"; print "verify with ls $fh after program exits"; readline STDIN; 

EDIT 1

I tested the behavior of a temporary file. This seems to confirm that Linux supports what I'm looking for (marking files as a temporary / unlocking open file). It seems I somehow idealized File :: Temp.

 # program will die because os deletes tmpfile after close my $fh = tempfile; close $fh; stat $fh || die; readline STDIN; 
+4
source share
5 answers

To cause the Control_C keyboard to interrupt to start the END block, you will need to add a signal handler. Compare the behavior:

 perl -E 'END{say "END"};<STDIN>' 

with:

 perl -E '$SIG{INT}=sub{die};END{say "END"};<STDIN>' 

From perlmod

 An END code block is executed as late as possible, that is, after perl has finished running the program and just before the interpreter is being exited, even if it is exiting as a result of a die() function. (But not if it's morphing into another program via exec, or being blown out of the water by a signal--you have to trap that yourself (if you can).) 
+2
source

Have you tried to put a cleanup code and an end block?

+2
source

I looked at the source code. I even checked the latest version (0.22 at the time of writing). What I want to do with the :: Temp file is not allowed by design.

When an object is created, a temporary file is created using the context of the array as:

 sub new { ... # Open the file and retain file handle and file name my ($fh, $path) = tempfile( @template, %args ); 

Creating a temporary file in the context of an array implies that the file will never be automatically disconnected (even on a platform that supports it). The file is marked for delayed unlock, which means that it will be deleted when the program exits normally.

 sub tempfile { ... _deferred_unlink($fh, $path, 0) if $options{"UNLINK"}; # Return if (wantarray()) { if ($options{'OPEN'}) { return ($fh, $path); } else { return (undef, $path); } } else { # Unlink the file. It is up to unlink0 to decide what to do with # this (whether to unlink now or to defer until later) unlink0($fh, $path) or croak "Error unlinking file $path using unlink0"; # Return just the filehandle. return $fh; } 

If I want to continue using File :: Temp, I need to set up a signal handler to force it to clear when my program is interrupted. I should also set up a sig handler if portability is any concern, because deferred unlink is all that is offered on some platforms. The best part is that File :: Temp creates an END block, so there is nothing to do:

 use sigtrap qw(die normal-signals error-signals); 

If portability is not a problem and the platform supports automatic file cleanup, then using tempfile is fine (in a scalar context).

The rationale for this design is explained by the following comment:

we must provide temporary information when opening the file. In general, we only need a true temporary file, if we return only a filehandle - if the user needs a file name, he probably does not want the file to disappear as soon as they close it (which may be important if they want the child process to use file)

+1
source

Do you really need a file name? If not, use

 my $fh = tempfile(); 
0
source

I was looking for something similar, and I think I found a pretty good, small solution.

This is nothing fundamentally new, but perhaps easier than installing your own END blocks, etc.:

 use sigtrap qw(die INT); # ensures DESTROY methods are run on Ctrl-C my $temp = File::Temp->new(UNLINK => 1); my $filename = $temp->filename; # When $temp goes out of scope, the file will be # deleted, and $filename will be invalid. # Further, a Ctrl-C will cause $temp->DESTROY to be invoked, # which will also delete the temp file. 
0
source

Source: https://habr.com/ru/post/1446321/


All Articles