Re: exec with cleanup
by roju (Friar) on Jun 07, 2004 at 14:14 UTC
|
END{
$ENV{"PARENT"} = $$;
if ($pid = fork()) {
//do whatever your script does to end
else {
wait({$ENV{"PARENT"}});
exec (foo);
}
}
Although considering how fork works, you could just do
END {
if ($pid = fork()) {
wait($pid);
exec(foo);
}
else {
//finish your process off
}
}
Now, either way, the process that wait's is still going to have a copy of all the descriptors and stuff, but that shouldn't be a huge problem. | [reply] [d/l] [select] |
Re: exec with cleanup
by blueAdept (Beadle) on Jun 07, 2004 at 14:07 UTC
|
here's a possible mechanism. At least on windows when used in this way the system() call won't block, it'll launch the command and the parent script continues on. The script returns immediately but if you watch your task manager the spawned perl process continues to run for 60 seconds.
This would seem an undocumented feature - I just glossed over perldoc for system & exec, and I don't see any mention of this behavior. But if the shoe fits .....
my $cmd = 'perl -e "sleep(60)"';
system(1, $cmd);
print "Done - but my subprocess is still running!\n";
| [reply] [d/l] |
|
I would rather use a documented method over an undocumented one. Know your shell.
system("start /b $cmd");
-- [ e d @ h a l l e y . c c ]
| [reply] [d/l] |
Re: exec with cleanup
by andyf (Pilgrim) on Jun 07, 2004 at 14:19 UTC
|
Im guessing this is for an embedded app Bart, or for some reason you're carefully counting memory bytes. At the point of exit
my understanding is that the only references still in scope
will be the builtins (@INC, @ARGS etc) and any globals.
All objects should have been undef, and you are not inside
a block that is holding onto any references the memory usage
should be minimal.
Let's clarify the problem further. Are you fearing a leak
because the external program will never return execution to
your first script? If so, how about forking? After spawning the external prog the script will continue through to a normal exit and cleanup.
Alternatively you could go right outside the box and realise that you could call both the original script and the followup program in sequence from another place.
Addition: Perls garbage collection is very solid.
From pp.451 of the Cookbook (Ram)
"So you're guaranteed that an object eventually gets properly destroyed, unless a program never exits."
GC gets called bigtime when the interpreter shuts down.
So another (horrible) solution presents itself, just get the followup program to kill its parent when it dies.
Andy | [reply] |
Re: exec with cleanup
by jsegal (Friar) on Jun 07, 2004 at 15:55 UTC
|
Perhaps the cleanest solution would be the prosaic wrapper script -- have a script run first your first program, then your second program. All cleanup would of necessity be completed by your first program. The outer wrapper (gasp) doesn't even need to be perl, but could be shell or .bat or whatever is appropriate for your platform.
#!/bin/sh
first_program args1
second_program args2
Alternatively, you could take advantage of the fact that END blocks are executed in the inverse order that they are defined, so if the very first END block your script encounters calls the exec, it will be the last bit of code run on cleanup. (see docs: http://www.perldoc.com/perl5.8.4/pod/perlmod.html#BEGIN%2c-CHECK%2c-INIT-and-END.
| [reply] [d/l] [select] |
Re: exec with cleanup
by cyocum (Curate) on Jun 07, 2004 at 13:43 UTC
|
A better way to do this would be to use the backtick operator, which returns the return code for the process when it returns or use the system call. That way you know when it ends and then can do some clean up before or after it. I hope this helps.
| [reply] |
|
But then I'd have to wait until the other script ends, before I can finally end this script. It would effectively keep both in memory at the same time. That doesn't look ideal.
| [reply] |
|
You can do system("perl script2.pl arg1 arg2 &"), which will return immediately. And system("nohup perl scrip2.pl arg1 arg2 &") won't die when the parent process exits.
| [reply] |
|
No, backtick does not "return the return code." Backtick (the qx// operator) returns the string of any output that the child process sends to STDOUT. The system() call does return the return code.
But he wants to abandon everything else in this script, flush all buffers, close all files, release all resources, and at the last possible moment, to jump to the beginning of a new program instead. The exec() function is just a little heavy-handed since it doesn't do all the cleanup first.
-- [ e d @ h a l l e y . c c ]
| [reply] [d/l] [select] |
Re: exec with cleanup
by blueAdept (Beadle) on Jun 07, 2004 at 17:05 UTC
|
I wonder if we're making this more complicated than need be. As perlmod says END blocks are executed last in first out, so if you want your END block to be last to execute just make sure its defined first. That isn't too hard is it? Maybe a little ugly - I know I usually place my END blocks at the end of my script, not the top.
From the below proof it seems to me that DESTROY blocks of objects are executed ahead of END blocks. So if you declare your END block first(so as to be the last to execute) then you should have reasonable assurance that your exec call will be the last thing to execute.(after all DESTROY and other END blocks) Can anyone see any holes in this?
use strict;
use warnings;
my $blessed_junk = testIt->new();
print "Time to exit outa here...\n";
exit 0;
sub END
{
print "THE END!\n";
}
package testIt;
sub new
{
my $junk = {};
bless $junk;
return $junk;
}
sub DESTROY
{
print "I'm dying!\n";
}
and the output is:
Time to exit outa here...
I'm dying!
THE END!
| [reply] [d/l] [select] |
|
# very very top of your first file
END {
if (@::final_exec) {
exec {$::final_exec[0]} @::final_exec;
}
}
# later that same day...
@::final_exec = ($^X, 'scriptname.pl', @args);
| [reply] [d/l] |
Re: exec with cleanup
by ambrus (Abbot) on Jun 07, 2004 at 19:51 UTC
|
If you are not on windows, you can fork, exit
cleanly in one process, and exec in the other.
| [reply] [d/l] [select] |