in reply to Re: Closing parent CGI after fork()
in thread Closing parent CGI after fork()

You probably want to close STDIN and STDERR too
  • Comment on Re: Re: Closing parent CGI after fork()

Replies are listed 'Best First'.
Re: Re: Re: Closing parent CGI after fork()
by edan (Curate) on May 04, 2004 at 13:49 UTC

    You probably want to close STDIN and STDERR too

    You probably don't want to do any of this stuff, but you'll find you have to... :(

    Even though the valuable information found by following links to merlyn's nodes/articles elsewhere in this thread only talk about closing STDOUT, I found I had to close STDIN and STDERR, as well. This is for Apache 2. I had to jump through some hoops to redirect the child's STDERR to a file and later send anything found there to the apache error_log, rather than lose any STDERR output produced by the child... a bit ugly, but it works.

    Also, I found I had to reopen all 3 filehandles (to/from /dev/null for STDOUT and STDIN, to a file for STDERR) as well, since my child is opening other files, and if you just close STD(IN|OUT|ERR), the next time you open a file it will get file descriptor 0, 1, or 2, which is essentially reopening STD(IN|OUT|ERR), and I found this causes apache to hang again! Ugh. forker beware!

    HTH

    --
    edan

      Thanks Edan.

      Well, I have done the project now, but take this into consideration for the upgrade - which I am already thinking about. My solution was to open a tiny browser window, make it the same colour as the background of the web page, and leave it running "hidden". A real cludge I know, but I really needed to move on here.
      Thanks for the advice anyway
      Couple of questions though:
      1. How do I go about re-opening STD(IN|OUT|ERR)?
      2. If I close STDOUT, how do I get hold of my STDOUT from the perl script or more importantly the system call?

      merlyn gave me a useful link to his long-running CGI process, but it did not work as I expected.
      I rather expected that every couple of seconds it would return, and update the page.
      Instead, it waited till the traceroute completed altogther before giving the results.
      I wondered whether this had to do with running it under Apache 2 rather than 1.3?
      Have you any comments on his long-running process?

      Thanks for your help though
      Cheers
      Hambo

      --
      Open Source - Where everything is QED
      Perl - where programming is FUN

        How do I go about re-opening STD(IN|OUT|ERR)?

        This is what I did:

        # throw away STDIN and STDOUT open STDIN, '<', '/dev/null'; open STDOUT, '>', '/dev/null'; # save STDERR to deal with later my $err_file = "/tmp/err.$$"; open STDERR, '>', $err_file;

        If I close STDOUT, how do I get hold of my STDOUT from the perl script or more importantly the system call?

        Well, as you see, you're not really closing STDOUT you are reopening it to some other place. This will cause all output that would ordinarily go to your program's standard STDOUT to go to the file specified in the open call above. That includes any output generated by system calls and the like, since it's going to the same filehandle, only in a child process in that case (system simply performs a fork and exec under the hood). If you needed to get your hands on that output, you'd have to direct it to a real file instead of /dev/null, as in the STDERR example above.

        HTH

        --
        edan