Thursday, April 24, 2014

A non-exceptional failure in the catch block

In various development versions of Crypt::SSLeay, I was specifying Devel::CheckLib as a dependency. In response to a request from a user, I decided to make it optional:

sub filter_libs {
    my $opt = shift;
    my $libs = shift;
    try {
       require Devel::CheckLib;
    catch {
       return $libs;


I am assuming the intent is obvious: If Devel::CheckLib is not available, just return the same list of libraries we were given. When using eval, it is easy to remember that eval { return "Hello" } does not return from the enclosing function. But, somehow, using the magic keywords try/catch, I forgot that! So, this check is completely useless, and execution continues regardless of the outcome of require.

Embarrassing, but true.

A simple:

return unless eval {
   require Devel::CheckLib;

would have worked. In fact, now that I am thinking about this, it probably would have been even better to use:

return $libs unless eval { require Devel::CheckLib; 1 };

That way, if the skip mechanism does not work, at least Makefile.PL crashes with a decent explanation.


  1. Your metadata is still wrong --

    That's because of this line: -- it should be prereqs => { ... }

    Moreover, things used in Makefile.PL should be *configure* prereqs, not build.

    If you're generating your META.* via Makefile.PL, be careful of META_ADD vs. META_MERGE - you don't want conditional prereqs (evaluated according to the conditions on *your* machine) to make it into META.* that everyone sees.

    -Ether (

    1. Thank you. I will fix that. I managed to squeeze way too many errors into this one.

    2. I am trying not to require Devel::CheckLib ... But, also convey via the meta mechanism that it is useful for this build. Maybe I misunderstood `recommends`.