> There are two things I'd suggest to try:
> 
> 1) pass $r to CGI->new($r), in which case it won't rely on the global 
> Apache->request. And you can switch then to 'PerlHandler modperl'.

I tried this first, no luck.

> 2) use the IO trace to debug what's going on:
> 
> you need to rebuild mp with MP_TRACE=1 and then add to httpd.conf:
> 
>    PerlTrace o
> 
> http://perl.apache.org/docs/2.0/user/config/config.html#C_PerlTrace_
> 
> compare the traces you get on the good and the bad machines.

I did this, and the result is interesting to me.

First, as a side note, when I put 'PerlTrace o' in the httpd.conf right off
the bat, Apache segfaulted on restart. So then I instead put the following
in the
<Perl> section: ' $ENV{MOD_PERL_TRACE} = "o";' and it started fine.

Oh and another side note... today I discovered that I am now seeing the
issue
from my own client here on my windows workstation *sometimes*. So it's no
longer
a per client issue.

The trace is quote noisy considering the size of the pages I am returning,
but
let me try to paraphrase the juicy bits (at least to my untrained eyes):

----- error_log ------
[Fri Oct 31 10:12:58 2003] [notice] SIGHUP received.  Attempting to restart
[Fri Oct 31 10:12:58 2003] [notice] seg fault or similar nasty error
detected in the parent process
mod_perl trace flags dump:
<SNIP (mp flags, IO is on everything else is off)>
<NOTE (this is where Apache segfaulted the first time, I made the httpd.conf
change, and restarted)>
[Fri Oct 31 10:16:13 2003] [warn] pid file /usr/local/apache/logs/httpd.pid
overwritten -- Unclean shutdown of previous Apache run?
[Fri Oct 31 10:16:13 2003] [notice] Apache/2.0.48 (Unix) mod_perl/1.99_10
Perl/v5.8.0 configured -- resuming normal operations
<SNIP (some seemingly inconsequential stuff)>
<NOTE (this is a request from my machine that usually works but didn't work
this time)>
*** reading POST data: CGI/usr/lib/perl5/5.8.0/CGI.pm518 at (eval 18) line
8.
PerlIOApache_read: wanted 3362b, read 189b
[f_table=R_rtrallint05m_&f_colour_availability_admin=%23F4E204&f_colour_avai
lability_oper
ational=%23F4B904&f_vars=bits_in&f_colour_bits_in=%23F4E204&f_vars=bits_out&
f_colour_bits_out=%23F4B9;
<SNIP (a bunch of perl code, see below... the brackets for the form data are
not closed until AFTER the code below!)>
PerlIOApache_write: 48 bytes [<HTML>
<SNIP (Apache writing my page which indicates there was no form data)>
<NOTE (this is the second request, again from my machine, again the
variables were apparently not readable)>
PerlIOApache_read: wanted 3361b, read 28b
[f_table=R_rtrallint05m_&f_cotipart {
<SNIP (the same code as per above, see below)
<SNIP (Apache again writes my page, the one for when there is no form data)>
<NOTE (this is the third request from me, which WORKS!)>
*** reading POST data: CGI/usr/lib/perl5/5.8.0/CGI.pm518 at (eval 18) line
8.
PerlIOApache_read: wanted 3361b, read 3361b
[f_table=R_rtrallint05m_&f_colour_availability_admin=%23F4E204&f_colour_avai
lability_ope
<SNIP (this time all my form data is there... notice it read all it wanted)>
<SNIP (Apache writes my page, the CORRECT page, which indicates that the
form data was available to my script>)
----- /error_log -----

So in summary, it seems there is an issue reading all the form data on the
requests that do not work. The variable that I use to determine which
sub-routine to call is the submit button which, not surprisingly, comes last
and so is being cut off. In case you missed it above, the square brackets
which are seemingly supposed to contain the data that is read are not closed
until AFTER the source code that appears. Buffer issues?

Just in case it is of interest, here is the source that is printed during
the failed read:

----- error_log ------
PerlIOApache_read: wanted 3362b, read 189b
[f_table=R_rtrallint05m_&f_colour_availability_admin=%23F4E204&f_colour_avai
lability_oper
ational=%23F4B904&f_vars=bits_in&f_colour_bits_in=%23F4E204&f_vars=bits_out&
f_colour_bits_out=%23F4B9;
    my(%header,$body);
    my $filenumber = 0;
    while (!$buffer->eof) {
        %header = $buffer->readHeader;

        unless (%header) {
            $self->cgi_error("400 Bad request (malformed multipart POST)");
            return;
        }

        my($param)= $header{'Content-Disposition'}=~/ name="?([^\";]*)"?/;
        $param .= $TAINTED;

        # Bug:  Netscape doesn't escape quotation marks in file names!!!
        my($filename) = $header{'Content-Disposition'}=~/
filename="?([^\"]*)"?/;
        # Test for Opera's multiple upload feature
        my($multipart) = ( defined( $header{'Content-Type'} ) &&
                $header{'Content-Type'} =~ /multipart\/mixed/ ) ?
                1 : 0;

        # add this parameter to our list
        $self->add_parameter($param);

        # If no filename specified, then just read the data and assign it
        # to our parameter list.
        if ( ( !defined($filename) || $filename eq '' ) && !$multipart ) {
            my($value) = $buffer->readBody;
            $value .= $TAINTED;
            push(@{$self->{$param}},$value);
            next;
        }

        my ($tmpfile,$tmp,$filehandle);
      UPLOADS: {
          # If we get here, then we are dealing with a potentially large
          # uploaded form.  Save the data to a temporary file, then open
          # the file for reading.

          # skip the file if uploads disabled
          if ($DISABLE_UPLOADS) {
              while (defined($data = $buffer->read)) { }
              last UPLOADS;
          }

          # set the filename to some recognizable value
          if ( ( !defined($filename) || $filename eq '' ) && $multipart ) {
              $filename = "multipart/mixed";
          }

          # choose a relatively unpredictable tmpfile sequence number
          my $seqno = unpack("%16C*",join('',localtime,values %ENV));
          for (my $cnt=10;$cnt>0;$cnt--) {
            next unless $tmpfile = new CGITempFile($seqno);
            $tmp = $tmpfile->as_string;
            last if defined($filehandle =
Fh->new($filename,$tmp,$PRIVATE_TEMPFILES));
            $seqno += int rand(100);
          }
          die "CGI open of tmpfile: $!\n" unless defined $filehandle;
          $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode;

          # if this is an multipart/mixed attachment, save the header
          # together with the body for lateron parsing with an external
          # MIME parser module
          if ( $multipart ) {
              foreach ( keys %header ) {
                  print $filehandle "$_: $header{$_}${CRLF}";
              }
              print $filehandle "${CRLF}";
          }

          my ($data);
          local($\) = '';
          while (defined($data = $buffer->read)) {
              print $filehandle $data;
          }

          # back up to beginning of file
          seek($filehandle,0,0);

      ## Close the filehandle if requested this allows a multipart MIME
      ## upload to contain many files, and we won't die due to too many
      ## open file handles. The user can access the files using the hash
      ## below.
      close $filehandle if $CLOSE_UPLOAD_FILES;
          $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode;

          # Save some information about the uploaded file where we can get
          # at it later.
          $self->{'.tmpfiles'}->{fileno($filehandle)}= {
              name => $tmpfile,
              info => {%header},
          };
          push(@{$self->{$param}},$filehandle);
      }
    }ðL]
----- /error_log -----

That's a lot of data, so I'll stop there. Let me know if what I am providing
is not clear or not what you are looking for.

Thanks,
Scott Beuker

Reply via email to