Hello,

I have a pretty big perl/tk application that uses HTTP connections and is cross-platform. I've tried many times to fork out the HTTP stuff so the GUI doesn't appear to hang while it waits for the HTTP request to come back, but Win32's limitations have until now caused major problems (cannot do the standard open(PIPE, "|-"), etc) ...

There's bigger problems here, too - Perl/Tk is not thread safe, and forking within a Tk application causes wierd errors. So I've got around this by forking at the start, before I use Tk;, and running a permanent child process with pipes to and from the parent.

So far, so good - the child recieves the http address to call from the parent, exits if this reads "exit" and otherwise fetches the http content. It then sends the content back to the parent, the parent reads this, and all is fine and dandy ...

... except I still end up with a blocked up GUI!!

I've tried using the standard method around this which is using fileevent() together with waitVariable(), but the catch here is that I need to read the content of the filehandle from the child in order to tell when to stop reading (i.e. - I send a signal from the child saying that all http content has been retrieved - since I can't close the child), and that's what blocks it all up! (if I don't do this everything runs as expected, but I can't get to the content since I never know when it's come!)

I need some way to check whether new data is available in the filehandle, without causing perl to wait until new data becomes available .... If anyone can think up a way around this, I'd really appreciate it!

Here's my test code...

#!/usr/bin/perl -w use strict; use LWP::UserAgent; use HTTP::Request; use IO::Handle; pipe(FROM_PARENT, TO_CHILD) or die "pipe: $!"; pipe(FROM_CHILD, TO_PARENT) or die "pipe: $!"; TO_CHILD->autoflush(1); TO_PARENT->autoflush(1); my $pid = fork; unless ($pid) { # Child process close FROM_CHILD; close TO_CHILD; die "cannot fork: $!" unless defined $pid; { chomp(my $address = <FROM_PARENT>); exit 0 if $address =~ /exit/; my $ua = LWP::UserAgent->new(); print "Child: getting $address ...\n"; # proxy server $ua->env_proxy(); my $req = HTTP::Request->new(GET => "$address"); my $response = $ua->request($req); my $http = $response->content; print "Child got the goods!\n"; print TO_PARENT $http,"\n"; print TO_PARENT "end_http_input\n"; redo; } exit 0; } # Parent process only ... use Tk; close FROM_PARENT; close TO_PARENT; my $top = MainWindow->new(-title=>"PerlPrimer v.test"); my $button = $top->Button(-text=>"try it!", -command=>\&do_it, )->pack(); my $quit = $top->Button(-text=>"Exit", -command=>sub { print TO_CHILD "exit\n"; exit 0; }, )->pack(); MainLoop(); sub do_it { # might as well put all these test http requests to good use . +.. :) my $address = "http://www.microsoft.com"; print TO_CHILD $address; my $unblock=0; my ($content, $data); $top->fileevent(\*FROM_CHILD, 'readable', sub { # This is where it hangs ... doesn't matter if I even go d +own to taking 1 byte at a time ... sysread(FROM_CHILD, $data, 32); $content.=$data; $unblock = 1 if $content =~ /end_http_input/; }); $top->waitVariable(\$unblock); $top->fileevent(\*FROM_CHILD, 'readable', ""); print "Parent: http content was $content\n"; print "out of loop ....\n"; }

BazB added readmore tags.


In reply to Forking Win32 ... by owenjm

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.