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

in fact i dont know why this doesnt work: its in a tk application a sub that starts a exterm script: (once more : workes fine under linux, but just doesnt under win2000 using ActivePerl)
$pid = open3 (\*CHILD_INPUT,\*CHILD_OUTPUT,\*CHILD_ERROR, "perl $scriptname $parameters"); close CHILD_INPUT; $main->fileevent(\*CHILD_OUTPUT,'readable',[\&fill_text_status]); $main->fileevent(\*CHILD_ERROR,'readable',[\&tackle_err_child]);
under win32 the appli is blocked after doing this ... but why?

----
NaSe
:x

Replies are listed 'Best First'.
(tye)Re: Win32 fork using open3
by tye (Sage) on Jun 05, 2002 at 16:46 UTC

    Contrary to popular belief, IPC::Open3 does not use fork under Win32. If indeed your open3() even comes from that module (you didn't say).

    And I see no hints as to what $main->fileevent is. It looks vaguely like an interface to 4-argument select. If so, then you probably don't know that 4-argument select in Win32 only works on sockets and so can't be used on pipes like you are trying to do there.

            - tye (but my friends call me "Tye")
      thanks that explains a lot ...

      so i guess its just that since select doesnt work under win32 that blocks the redrawing of my Tk-frontend when the script is executed ...

      so is there a way to execute a script in a nonblocking way under win32 ?

      ----
      NaSe
      :x

Re: Win32 fork using open3
by alien_life_form (Pilgrim) on Jun 05, 2002 at 13:23 UTC
    Greetings,

    I would place my bets on the fork() emulation that,as can be found elsewhere on PM, does not properly shine on Win32.
    AFAIK, open3 does implicitly fork...
    Cheers,
    alf


    You can't have everything: where would you put it?
      i can see that there is a need to to implicitly fork() to implement open3 ... and i also can see it in the code of Open3.pm ... but i still cant see why this doesnt work on win32 ... since i have forked before on win32 using perl and it worked .

      is there another way to do something like open3 not using the acual command?

      ----
      NaSe
      :x

      tye is correct. In fact anything named open (IPC::Open3, IPC::Open2 {A wrapper for Open3}, open) does an *implicit* fork. Which in Win32's case are not real faked up forks, and work quite well. Afterall you were always able to open pipes in Win32, even when fork hadn't been faked.

      --
      perl -pew "s/\b;([mnst])/'$1/g"

Re: Win32 fork using open3
by coreolyn (Parson) on Jun 05, 2002 at 13:59 UTC

    I've been having good results on both *nix and Win32 with this code. It executes well over 200 times whenever it's parent application is run and I have about a dozen Windows Users and about 30 *nix users running it about 20 times per day each. Some of the code there isn't doing anything, however the use of the IO::Select seemed to make a big difference in the problems I had been expiriencing previous to implementing it. I will confess that with the above listed usage I have had 2 reported mysterious hangs, but I can't verify that open3 was the cause of those, and simply running the script again would not reproduce the problem in either case.

    coreolyn
      i also tried that but i wont work with my code...

      i've tried it also with Win32::Process ... I think that this might be THE chois , but it rests the nonblocking IPC and i dont know how to realize that

      ----
      NaSe
      :x

Re: Win32 fork using open3
by Aristotle (Chancellor) on Jun 05, 2002 at 12:52 UTC
    IPC::Open3 does not work on non-Unix(ish) systems.

    Makeshifts last the longest.

      Hmm, actually looking into the module, I'm wrong - line 88:# ported to Win32 by Ron Schmidt, Merrill Lynch almost ended my career____________
      Makeshifts last the longest.
        # ported to Win32 by Ron Schmidt, Merrill Lynch almost ended my career

        I wonder what the story is behind that comment :)

        I'm also wondering how much that's going to come back to haunt him, whoever he is...
        --
        Mike

      where did you get this from (since there is nothing like this in the man-page - at least i dont see it)

      ----
      NaSe
      :x

Re: Win32 fork using open3
by NaSe77 (Monk) on Jun 19, 2002 at 11:52 UTC
    finaly found a souloution that works its a bit different from my first approch but it works (in fact the solution is to use a socket and to "poll" the socket yourself ....) something like this :
    #!/urs/bin/perl -w use strict; use warnings; use IO::Socket; use Tk; use subs qw/read_sock/; my $mw; my $sel; my $sock; my $text; my $line; my $scriptname = "my_script.pl"; #some Tk $mw = MainWindow->new(); $text = $mw->Text->pack; my $goButton = $mw->Button( -text=> "Accept", -command => \&go )->pack( -side=>"left", ); #"polling" socket $mw->repeat(50 => \&read_sock); MainLoop; sub read_sock{ return unless $sock; my $hand = $sock; my @ready = $sel->can_read(0); return if $#ready == -1; $hand = $ready[0]; my $numbytes = 1; my $buf; sysread $hand, $buf, $numbytes; print "read a $buf\n"; $line .= $buf; if ($buf eq "\n"){ if ($line eq "EOF\n"){ undef $sel; undef $sock; undef $line; return; } $text->insert('end',"$line"); undef $line; } } sub go{ my $ProcessObj; require Win32; require Win32::Process; Win32::Process::Create($ProcessObj, "c:\\perl\\bin\\perl.exe", "perl $scriptname", 0, 0, ".")|| die ErrorReport(); sleep 2; # let the script time to built the socket $sock = IO::Socket::INET->new(PeerAddr=> 'localhost:13579'); die "cannot connect: $!\n" unless defined $sock; use IO::Select; $sel = IO::Select->new(); $sel->add($sock); }
    and in $scriptname
    #!/usr/bin/perl -w use IO::Socket; use strict; my $socket = IO::Socket::INET->new( Listen => 5, Reuse => 1, LocalPort => 13579, Proto => 'tcp', )||die "couldn't open socket : $!\n"; my $new_socket = $socket -> accept(); #so far so good #if the is $something_to_say syswrite $new_socket, "$something_to_say\n";
    and to sigal the end to the parent (since there is no sigchld when using Win32::Process)
    END{ syswrite $new_socket, "EOF\n"; }

    ----
    NaSe
    :x

      i'm sorry i can't look closely at your code now, but after a quick browse i noticed you aren't checking the return codes from sysread and syswrite -- you should.

      ~Particle *accelerates*

        that is right and a good idea ... did u have something like
        my $read_bytes = sysread $hand, $buf, $num_bytes; die "error occured reading from socket : $!\n" unless ($read_bytes && ($read_bytes == $num_bytes));
        and the same for the writing in mind ?

        ----
        NaSe
        :x