in reply to IPC::Run harness question

G'day italdesign,

"So for some reason, finish() doesn't seem to be getting the proper $h object."

The most likely reason is that you're using package global variables. If you move code from one package to another, the variables in that code will be global to the new package. Use lexical variables!

Using package global variables will have other problems; for instance, in the code you show, you don't capture the object invoking your methods but instead just use whatever value $self happens to have.

Furthermore, the code you have provided appears to have problems which strict would have alerted you to: 'vars' would tell you about "$self" and "$h" and 'subs' would tell you about "h". strict may find other problems in your complete code; warnings will alert you to other types of problems.

To save yourself from another potential bug which can be hard to track down, I'd recommend you stop using the strongly discouraged Indirect Object Syntax.

-- Ken

Replies are listed 'Best First'.
Re^2: IPC::Run harness question
by italdesign (Novice) on May 05, 2014 at 20:29 UTC
    Hi Ken, thanks for taking the time to reply. I'm actually not using package global variables. I should have included a few more lines:
    package IPC_Class use strict; use warnings; sub new { shift; my $self = { 'cmds' => undef, @_ }; defined $self->{'cmds'} or die "ERROR: didn't get CMD in constructor +."; IPC::Shareable->clean_up_all; bless $self; return $self; } sub start { my $self = shift; my $fh_glob_ref = shift; ... # the cmd "grep 'zzz'" in the next line will fail. my $h = IPC::Run::start(['sort'], '<pipe', $fh_glob_ref, '|', ['grep +', 'zzz'], '>', $writefh, "2>", $writefh) or die "Error: $!\n"; $self->{'h'} = h; } sub finish { my $self = shift; $h = $self->{'h'}; if (!$h->finish()) { for ($h->full_results) { print "$_\n" }; } }
    I'm really lost as to why it's not working :( The code in my start() method works beautifully. And if I move the code in my finish() method to the main program (having start() return $h), where I extract the data out of $h, then it works fine. But having the code in finish() and calling $o->finish() SOMEHOW loses the data in $h.

    (Thanks for the note on IOS. Lesson learned.)

      "I'm actually not using package global variables."

      Then you need to show the declaration of the lexical variables you are using.

      In:

      sub finish { ... $h = $self->{'h'}; ... }

      The scope of $h is not confined to &finish but it should be. You don't show where it's declared or what else uses this $h (with global-like scope). When you move the code in &finish to another package, a different global-like $h will be involved.

      In:

      sub start { ... $self->{'h'} = h; }

      I don't know what &h is doing: you don't show a sub h {...} definition. Maybe that's related to the problem. And, of course, h being a subroutine call is just a guess on my part: for all I know, it could be a directory handle.

      I recommend you reduce this down to the shortest amount of code which reproduces the problem ["How do I post a question effectively?" provides guidelines for achieving this]. Doing so, may actually highlight your problem such that you can resolve it yourself. If it doesn't, at least there's something we can run without having to guess what code you haven't shown.

      -- Ken

        Sorry about that Ken. I mistyped a few times even in the revised version. But it looks like the problem is actually due to forking and waitpid. I've posted it as a separate question, with complete minimum code this time.