Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

I think I'm misunderstanding $|

by sigmazero13 (Novice)
on Dec 17, 2007 at 22:24 UTC ( #657532=perlquestion: print w/ replies, xml ) Need Help??
sigmazero13 has asked for the wisdom of the Perl Monks concerning the following question:

I'm having some issues with some web code I'm writing. It's supposed to print the values that the user input, then do some processing (the printout is just to verify to the user that it got the data, so they don't think the sometimes-long-wait means that it's locked up). Here's some of the relevant code:
$| = 1; select(STDERR); $| = 1; select(STDOUT); $| = 1; print <<END_HTML; Content-type: text/html \n\n <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> END_HTML #reads the input values here print END_HTML; <title>PAGE TITLE</title> <!--OTHER HTML HEADER STUFF--> </head> <body> <!--VISIBLE PAGE HEADINGS AND STUFF--> END_HTML print "value: $value<br>"; # the above line is repeated for each input value open(temp_handle, "> log_file"); print(temp_handle "log stuff"); #repeated with information close temp_handle; system("external_program"); # the above program can take several seconds to several # minutes to run print <<END_HTML; </BODY> </HTML> END_HTML
What happens is that it displays on the client everything up to and including the "visible page headers" stuff, but none of the values. However, when I set $| = 0 for the STDOUT one, it prints everything and then does the processing. Am I misunderstanding how $| works?

Comment on I think I'm misunderstanding $|
Download Code
Re: I think I'm misunderstanding $|
by shmem (Canon) on Dec 17, 2007 at 22:42 UTC
    Am I misunderstanding how $| works?
    Probably not. But there are other errors.
    select(STDERR); $| = 1;

    Well, no error, but need for that. STDERR is auto-flushed by default. Delete those \n\n after your Content-type header. Those are an error.

    Typo here:

    #reads the input values here print END_HTML; <title>PAGE TITLE</title>

    should be

    print <<END_HTML;

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      Oops, sorry about the typos. I guess I didn't realize that about STDERR, I'll take that part out. (I'm actually updating someone else's code here, but that doesn't absolve me of not cleaning it up properly). As for the \n\n after the Content-type header, why is that an error? It prints correctly. I didn't put them there specifically, but I think the original author did that to ensure that the HTTP Header was definitely "done" before starting (but I could remove it).
        Content-type: text/html \n\n <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML>

        places 4 newlines bewteen "html" and "<!DOCTYPE", which means "<!DOCTYPE" is on the third line of the body but I think the specs requires it to be on the first line. Just leave a blank line between "html" and "<!DOCTYPE".

Re: I think I'm misunderstanding $|
by friedo (Prior) on Dec 17, 2007 at 22:44 UTC
    Looks like you forgot the << on the second heredoc name. You would have gotten a useful error to that effect if you had warnings turned on.
      Yeah, that was just a typo in entering it onto the site here :) It has the << in the source. :)
Re: I think I'm misunderstanding $|
by ikegami (Pope) on Dec 17, 2007 at 22:45 UTC

    Works fine for me, until I add the browser to the equation.

    The program I used:

    #!/usr/bin/perl $| = 1; print <<'END_HTML'; Content-type: text/html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <title>PAGE TITLE</title> </head> <body> <p>Start. END_HTML sleep(5); print <<'END_HTML'; <p>done. </BODY> </HTML> END_HTML

    Running it from the prompt:

    $ foo.cgi Content-type: text/html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <title>PAGE TITLE</title> </head> <body> <p>Start. ...waits 5 secs... <p>done. </BODY> </HTML>

    Running it from via the web server:

    $ telnet www.example.com 80 Trying 11.22.33.44... Connected to www.example.com. Escape character is '^]'. GET /script.cgi HTTP/1.0 Host: www.example.com HTTP/1.1 200 OK Date: Mon, 17 Dec 2007 22:39:09 GMT Server: Apache/2.0.54 (Unix) PHP/4.4.7 mod_ssl/2.0.54 OpenSSL/0.9.7e m +od_fastcgi/2.4.2 DAV/2 SVN/1.4.2 Vary: Accept-Encoding Connection: close Content-Type: text/html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <title>PAGE TITLE</title> </head> <body> <p>Start. ...waits 5 secs... <p>done. </BODY> </HTML> Connection closed by foreign host.

    But when viewed in FireFox 2, it waits for the entire document to arrive before display it.

      Hmm, that is very strange. I guess I'll have to look and see if there's a way to force the browser to output immediately.
        You're barking up the wrong tree, if you ask me. See merlyn's column on long-running CGI processes.
      I just tried this under Apache 1.3.34 (ancient I know, but it was handy) and Firefox 2.0.11, and it renders the text immediately. Even if I replace the sleep 5 with this:
      for (1..15) { print; sleep 1; }
      it will update the page once per second.

      You might check if you are using a web proxy. The proxy could accumulate text before forwarding it to the browser.

      One thing to try is to terminate the current HTML element with something like <br> or <p>. As ikegami mentioned, it is not easy for the browser to guess exactly when it is time to update the display, and a paragraph break might give it a better clue.

      If all else fails, you could use DHTML: give an html id attribute to an HTML element you want to update, and spit out snippets of Javascript to update the element attributes. I have done that where a table in the middle of the page needed to be updated as the script in back of the page ran. It's pretty to watch it run, but it's not at all pretty to write, especially if you have to support both IE and FireFox.

      But when viewed in FireFox 2, it waits for the entire document to arrive before display it.

      We had that before. See Re: Clever autoflush detail.

      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: I think I'm misunderstanding $|
by andye (Curate) on Dec 18, 2007 at 20:45 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://657532]
Approved by kyle
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (8)
As of 2014-12-25 20:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (163 votes), past polls