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

in redo question ( part 'catching segfaults' ) i tried to figure out where an app was segfaulting, and why. i found the where and the why, i think.

running a job as root, attempting to overwrite files owned by nobody, did weird stuff ... i can't explain it. i put in a lot of extra  -e $filename checks to avoid overwriting the files ... and now the script runs just fine.

so why would this segfault?

note: more code added for completeness:

calling CGI script:

my $mainImg = $self->query->param('propImg'); my $id = $self->query->param('pId') || $self->param('DBH')->{mysql_insertid}; if ($mainImg) { warn " ( $id ) directory ... " . FINALDIR if DEBUG; my $utils = MLSUtils->new(); my $fsName = $utils->save_to_filesystem( $self->query, FINALDIR, 'propImg +' ); my ( $base, $dir, $suffix ) = fileparse( $fsName, qr{\..*} ); my $newImgName = FINALDIR . "/LG${id}_0" . $suffix; warn "passing $newImgName to resizeImg " if DEBUG; $utils->resizeImg( $fsName, $newImgName, 1 ) or die "Resizing images failed! "; $sth = $self->param('DBH')->prepare( "UPDATE jbg_managed_props SET NumPhotos = 1 WHERE jbgPropertyID = ? " ); $sth->execute($id) if ( !$self->query->param('pId') ); } warn "back from images " if DEBUG;
MLSUtils.pm
sub resizeImg { my ( $self, $imageName, $newImageName, $mkThumb ) = @_; die("Cannot resize null image value") unless ($imageName); warn "before regex: imageName --> $imageName " if DEBUG; warn "before regex: newImageName --> $newImageName " if DEBUG; my ( $base, $dir, $suffix ) = fileparse( $imageName, qr{\..* +} ); my ( $base2, $dir2, $suffix2 ) = fileparse( $newImageName, qr{\..* +} ); $base2 =~ s/LG/TH/; my $tmpName = IMAGEDIR . '/' . $imageName; my $fileName = $newImageName; my $large = Image::Magick->new() or die "NO IMAGE READ!!!: $!"; my $filesRead = $large->Read($imageName); my $thumb = $large->Clone(); my ( $height, $width ) = $large->Get( 'height', 'width' ); my $reduceWlg = LG_MAX_WIDTH / $width; my $reducePercent = $reduceWlg; my $newH = $height * $reducePercent; my $newW = $width * $reducePercent; warn "new IMG: $fileName " if DEBUG; my $attempts; FILEWRITE: { $attempts++; eval { open( NEWIMG, ">$fileName" ) or die "Can't open new imagefile: ($fileName) $! \n"; binmode(NEWIMG); warn "after OPEN and BINMODE" if DEBUG; ###3 don't forget! Image::Magick functions don't have ret +urn values $large->Resize( height => $newH, width => $newW ) ; # or die "Resizing error: $! \n"; warn "RESIZE worked! " if DEBUG; $large->Write( file => \*NEWIMG ); # or die "Write erro +r: $!\n"; warn "WRITE worked! " if DEBUG; close(NEWIMG); }; warn "trying to write the new file ( $fileName ) failed: $@ " +if ($@); redo FILEWRITE if ( $@ and $attempts < 3 ); } #undef $large; warn "New LG image written" if DEBUG; if ($mkThumb) { my $thumbName = "${dir2}/${base2}${suffix2}"; warn "thumb : $thumbName " if DEBUG; my $reduceWth = TH_MAX_WIDTH / $width; $reducePercent = $reduceWth; $newH = $height * $reducePercent; $newW = $width * $reducePercent; $thumb->Resize( height => $newH, width => $newW ); open( NEWIMG, ">$thumbName" ) or die "Can't open new imagefile: ($thumbName) $! \n"; $thumb->Write( file => \*NEWIMG ); close(NEWIMG); warn "New TH image written" if DEBUG; } warn "exiting sub resizeImg()" if DEBUG; return 1; }
output in error_log
[Wed Jul 14 19:10:13 2004] admin.cgi: passing /home/httpd/jbgoodwin.co +m/html/image/LG6_6.jpg to resize img at /home/httpd/jbgoodwin.com/lib +s/AdminFunctions.pm line 394. [Wed Jul 14 19:10:13 2004] admin.cgi: before regex: imageName --> /ho +me/httpd/jbgoodwin.com/html/image/Provance Model living 6.jpg at /ho +me/httpd/jbgoodwin.com/libs/MLSUtils.pm line 84. [Wed Jul 14 19:10:13 2004] admin.cgi: before regex: newImageName --> +/home/httpd/jbgoodwin.com/html/image/LG6_6.jpg at /home/httpd/jbgood +win.com/libs/MLSUtils.pm line 85. [Wed Jul 14 19:10:13 2004] admin.cgi: new IMG: /home/httpd/jbgoodwin. +com/html/image/LG6_6.jpg at /home/httpd/jbgoodwin.com/libs/MLSUtils. +pm line 108. [Wed Jul 14 19:10:13 2004] admin.cgi: after OPEN and BINMODE at /home/ +httpd/jbgoodwin.com/libs/MLSUtils.pm line 119. [Wed Jul 14 19:10:13 2004] admin.cgi: RESIZE worked! at /home/httpd/j +bgoodwin.com/libs/MLSUtils.pm line 123. [Wed Jul 14 19:10:13 2004] admin.cgi: WRITE worked! at /home/httpd/j +bgoodwin.com/libs/MLSUtils.pm line 126. [Wed Jul 14 19:10:13 2004] admin.cgi: New LG image written at /home/ht +tpd/jbgoodwin.com/libs/MLSUtils.pm line 136. [Wed Jul 14 19:10:13 2004] admin.cgi: exiting sub resizeImg() at /home +/httpd/jbgoodwin.com/libs/MLSUtils.pm line 158. [Wed Jul 14 19:10:13 2004] [error] [client 24.173.210.82] Premature en +d of script headers: /home/httpd/jbgoodwin.com/html/admin/admin.cgi
no reason for dying, just death. i have another smaller cron-based script which uses the same ImageUtils lib, and it shows the the segfault ( when run via commandline )

i see the "existing sub resizeImg()" warn, but never the "back from images" warn ...

Replies are listed 'Best First'.
Re: segfault on writing an image?
by BrowserUk (Patriarch) on Jul 15, 2004 at 00:59 UTC

    What happens if you comment out these two lines?

    $sth = $self->param('DBH')->prepare( "UPDATE jbg_managed_props SET NumPhotos = 1 WHERE jbgPropertyID = ? " ); $sth->execute($id) if ( !$self->query->param('pId') );

    Does the segfault go away?

    It looks like your passing your DBI handle as a CGI parameter and then expecting it to work as one once it has been sent to the client and returned?

    I'm not a CGI person, but I wouldn't expect that to work.

    My apologies if $self is not a CGI object.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
      well,  $self is a CGI::Application object. that's not the issue ... thx though.
Re: segfault on writing an image?
by hossman (Prior) on Jul 15, 2004 at 01:44 UTC

    I'm with BrowserUK .. that use of "$self->param('DBH')->prepare" strikes me as extremely fishy. But i can't be sure that anything weird is going on there, since you didn't include your whole CGI (where is $self initialized? what does "$self->param('DBH')" return? is it a real DBI database handle, or something of your own creation? .. we aren't mind readers you know.)

    I also suspect that maybe the Segfault you see in your cron may not be the same problem as what you see in your CGI .. since the libraries "resizeImg" seems to be returning fine. (However, it's hard to be sure about that either, since I'm not entirely clear on what the two have in common -- you say the method is in "MLSUtils.pm", but later you say your cron uses "the same ImageUtils lib" .. so i'm not sure what you mean)

      the ImageUtils lib is really named MLSUtils ...

      i *think* i found a fix, BTW. explicitly setting the  $large var, which is the Image::Magick object, seems to fix it, since the pre-return warning print, but the post-return warning (in the caller) never does. i *think* that somehow the vars in MLSUtils going out of scope is kicking something ...

Re: segfault on writing an image?
by pbeckingham (Parson) on Jul 14, 2004 at 23:09 UTC

    You need to run this through perltidy, if not for your benefit, then for ours. But more importantly, could you provide us with the output that this code generates?

    Because without sample output, and all the assumed inputs, we can't run the program for ourselves and debug.

      well, i ran it through perltidy as requested, and added parts of the calling app, more of the module, and lines from the error_log (to show the warnings that are output)
Re: segfault on writing an image?
by iburrell (Chaplain) on Jul 15, 2004 at 17:29 UTC
    A segfault is not going to give a reason. The problem is likely in the Image::Magick module since that is a complex XS module. And I am going to guess that the smaller script is not using CGI or DBI. If the smaller script isn't just testing the image routing, I would suggest writing a test for just the function that is crashing.

    It could be a build problem: what version of Perl are you using? What version of Image::Magick? What version of ImageMagick library? Was the module compiled for this version of Perl and ImageMagick library? Did you compile the module or is it a distributed package? Are you using the most recent versions?

      actually, the smaller, run-via-cron script does use DBI ...

      i don't know whic versions without trying to check each one individually, and even then, i couldn't tell you if the previous person built them from RPM or from source ...

      i found another possible reason for the crashing -- trying to resize a non-existent image. the person who wrote one component fetched the images from a remote site via  system( "wget" ... blah blah ) which doesn't really have much status to check.

      i added an existence check on the attempted image, and that seemed to make the bug go away. just got *more* defensive.