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

seems some Image::Magick stuff i have decided to stop working recently. either that, or there's something wrong with the image i'm trying to resize.

i wanted to try and catch the error, and attempt another resize-and-write with a named block, eval, and redo

from reading the perldoc on redo, i find this:

"redo" cannot be used to retry a block which returns a value such as + "eval {}", "sub {}" or "do {}", and should not be used to exit a gre +p() or map() operation.

which makes me think a code block like this won't DWIM:
warn "new IMG: $fileName " if DEBUG; FILEWRITE: { eval { open( NEWIMG, ">>$fileName" ) or die "Can't open new image +file: ($fileName) $! \n"; binmode( NEWIMG ); $large->Resize( height => $newH, width => $newW ); # or di +e "Resizing error: $! \n"; $large->Write( file => \*NEWIMG ); # or die "Write error: + $!\n"; close( NEWIMG ); }; warn "trying to write the new file ( $fileName ) failed: $@ " +if ( $@ ); redo FILEWRITE if ( $@ ); } undef $large; warn "New LG image written" if DEBUG;
from here, i just return if no thumbnail img is needed, or create one.

i get the first DEBUG line printed to STDERR, but not the second one on a segfault, so i've gotten to the point where it's the FILEWRITE block ... but, i'm not sure *exactly* which part is failing.

so ...

  1. will this redo construct work, or is this one of those explicitly mentioned as not working in the perldoc (i'd think it works since i'm explicitly testing for $@
  2. what could be causing the segfault?
edited: removed the "or die" from the Image::Magick calls ... i added them back in debug, but forgot that they don't have a return value. hoorah infinite loop!

edit 2: after more testing/fighting, it seems that the calling app is segfaulting between a  warn statement and a  return 1; statement. i added a warning right after the object method is called ... and i never see it.

in the calling app:

unless ( -e $useFile and $needThumb && -e $checkThumb ) { warn "resizing $useFile ( and $checkThumb )"; my $resizeOK = $utils->resizeImg( $baseImg, $useFile, $needThum +b ); } warn "done resizing in main app " ;
i never see that last warning ... man, am i ever stuck

Replies are listed 'Best First'.
Re: redo question ( part 'catching segfaults' )
by rjbs (Pilgrim) on Jul 14, 2004 at 17:47 UTC
    You can't redo a block that returns, but you can redo a block that /contains/ a returning block.

    OK:

    my $foo = 1; BLOCK: { last if $foo > 10; eval { print $foo++, "\n"; }; redo; }
    NOT OK
    my $foo = 1; eval { last if $foo > 10; print $foo++, "\n"; redo; }
    rjbs
Re: redo question ( part 'catching segfaults' )
by ysth (Canon) on Jul 14, 2004 at 17:48 UTC
    That redo should work, but:
    do { eval { ... }; warn ... } while ($@);
    would do just as well; is there a reason to prefer the bare block?

    Do you really mean be appending to NEWIMG?

    I'm not sure what error you are expecting to get that you would want to retry. Seems like anything that is going to fail is going to fail repeatedly. But I know nothing of ImageMagic.

      i prefer bare blocks, just as a style thing. they make more sense to me than  do ... while blocks.

      no, i don't mean to be appending. that's something else i noticed. it *really* won't append, because there should never be a file there by the name, but making sure doesn't hurt.

      well, the *thought* is that it's a transitory error ... hence the retry. but, i can't assume that it's transitory, so i'm adding a  $attempts var, and moving on if  $attempts > 3

Re: redo question ( part 'catching segfaults' )
by dave_the_m (Monsignor) on Jul 14, 2004 at 18:37 UTC
    Note that eval won't catch segfaults.

    Dave.

      well, i couldn't remember if it did or not, so it doesn't hurt to try.

      i *seems* at this point that the calling app is segfaulting, not the resizing code ... i've liberally salted the code with  warn " this or that ... " if DEBUG;, and the resizing works, the object method is supposed to return ( and i get the warning that it's about to do so ), BUT i don't see the warning after the object method returns ...