zentara has asked for the wisdom of the Perl Monks concerning the following question:

I'm making a mini module for my own use, and although I'm getting it to work, I'm wondering if this is the best way to do this. What I'm try to do is load a module and have it fork and exec some code. It's very easy when the code is a separate script like:
package MeM; use warnings; use strict; use vars qw(@ISA @EXPORT_OK); @ISA = qw(Exporter); # inherit the import() from Exporter.pm @EXPORT_OK = qw(init); # list of things to export if asked to my $pid = $$; if(fork() == 0){exec '/home/zentara/perl5lib/memmonitor',$pid } 1;

That's working good, but requires the script to be a separate file. So after alot of hacking( and failures), I finally got the following to work. But is it any good? I had to use the weird perl shebang because exec wanted shell syntax.

package MeMz; use warnings; use strict; use vars qw(@ISA @EXPORT_OK); @ISA = qw(Exporter); # inherit the import() from Exporter.pm @EXPORT_OK = qw(); # list of things to export if asked to ################################################# my $pid = $$; my $perl=<<'EOP'; eval 'exec perl -S $0 "$@"' if 0; use Tk; my $mw = new MainWindow; $mw->overrideredirect(1); my $t = $mw->Label(-text=>'', -bg=>'black', -fg=>'yellow')->pack; my $id = Tk::After->new($mw,1000,'repeat',[\&refresh,$pid]); MainLoop; sub refresh{ my $pid = shift; my @size = split "\n", `cat /proc/$pid/status`; (my $vmsize) = grep {/VmSize/} @size; my (undef,$size) = split ' ',$vmsize; $t->configure(-text=>"PID: $pid -> $size"); if($size eq ''){Tk::exit} } EOP if(fork() == 0){ exec (eval $perl ) } 1;

I'm not really a human, but I play one on earth. flash japh

Replies are listed 'Best First'.
Re: fork and exec a codeblock
by Aristotle (Chancellor) on Mar 16, 2004 at 19:32 UTC
    I am confused. Why do you need to exec if the code is Perl anyway and you have control of both processes and the source for both?
    package MeMz; use warnings; use strict; use vars qw(@ISA @EXPORT_OK); @ISA = qw(Exporter); # inherit the import() from Exporter.pm @EXPORT_OK = qw(); # list of things to export if asked to if (fork() == 0) { require Tk; my $mw = new MainWindow; $mw->overrideredirect(1); my $t = $mw->Label(-text => '', -bg => 'black', -fg => 'yellow')-> +pack; my $id = Tk::After->new($mw, 1000, 'repeat', [ \&refresh, $pid ]); Tk::MainLoop(); sub refresh { my $pid = shift; my @size = split "\n", `cat /proc/$pid/status`; (my $vmsize) = grep { /VmSize/ } @size; my (undef, $size) = split ' ', $vmsize; $t->configure(-text => "PID: $pid -> $size"); if ($size eq '') { Tk::exit } } } 1;
    Update: s/MainLoop/Tk::MainLoop()/

    Makeshifts last the longest.

      require Tk; ... MainLoop;
      That's not going to work. Since the sub isn't declared at the time "MainLoop;" is compiled, it is a bareword (and the use strict will make it die with 'Bareword "MainLoop" not allowed while "strict subs" in use').

      In general you can't just replace use with require without other changes. In this case, I think saying &MainLoop(); is the only needed change. Update: and add an import Tk; after the require.

        Good catch. Actually, &MainLoop(); will still be an error since require doesn't give the module a chance to export anything, and you either have to do that manually or prefix things with the right package.

        Of course, none of this has much to do with the forking question..

        Makeshifts last the longest.

Re: fork and exec a codeblock
by zentara (Cardinal) on Mar 17, 2004 at 15:57 UTC
    Thanks Aristotle for demonstrating that. I guess my original idea was to to try and separate the monitoring code from the monitored code.

    It seems now that it is preferrable to have the script in a separate file. rather than a code block, because when watching it with ps or top, the forked codeblock is almost 9 meg in size, whereas the forked separate file is only around 4 meg. Maybe it's getting the xterm in there with it?

    Although it is non-Perl, I discovered that the assembly sh, grep,watch,and cat from the asmutils collection at asmutils will monitor it extremely efficiently with:

    #!./sh ./watch ./cat /proc/$pid/status | ./grep VmSize
    and it uses only 40k (including the shell) !!! Yikes....I'm getting interested in Inline::Asm again.

    Now I'm searching for a way to display the asm output to a nice screen box, directly without Tk. :-)


    I'm not really a human, but I play one on earth. flash japh