As noted in the Try::Tiny man page, eval/$@ can be quite awkward in
corner cases, because $@ has the same properties and problems as C's
errno. While writing a regression test for definetemplate
in which it couldn't find an appropriate template, I received
<span class="error">Error: failed to process template
<span class="createlink">deftmpl</span> </span>
instead of the intended
<span class="error">Error: failed to process template
<span class="createlink">deftmpl</span> template deftmpl not
found</span>
which turned out to be because the "catch"-analogous block called
gettext before it used $@, and gettext can call define_gettext,
which uses eval.
This commit alters all current "catch"-like blocks that use $@, except
those that just do trivial things with $@ (string interpolation, string
concatenation) and call a function (die, error, print, etc.)
{ FileName => "$config{wikistatedir}/sessions.db" })
};
if (! $session || $@) {
{ FileName => "$config{wikistatedir}/sessions.db" })
};
if (! $session || $@) {
- error($@." ".CGI::Session->errstr());
+ my $error = $@;
+ error($error." ".CGI::Session->errstr());
- $feed->{message}=gettext("feed crashed XML::Feed!")." ($@)";
+ # gettext can clobber $@
+ my $error = $@;
+ $feed->{message}=gettext("feed crashed XML::Feed!")." ($error)";
$feed->{error}=1;
debug($feed->{message});
next;
$feed->{error}=1;
debug($feed->{message});
next;
$template=template($feed->{template}, blind_cache => 1);
};
if ($@) {
$template=template($feed->{template}, blind_cache => 1);
};
if ($@) {
- print STDERR gettext("failed to process template:")." $@";
+ # gettext can clobber $@
+ my $error = $@;
+ print STDERR gettext("failed to process template:")." $error";
return;
}
$template->param(title => $params{title})
return;
}
$template->param(title => $params{title})
check_canattach($session, $final_filename, $tempfile);
};
if ($@) {
check_canattach($session, $final_filename, $tempfile);
};
if ($@) {
- json_response($q, $form, $dest."/".$filename, $@);
- error $@;
+ # save error in case called functions clobber $@
+ my $error = $@;
+ json_response($q, $form, $dest."/".$filename, $error);
+ error $error;
}
# Move the attachment into holding directory.
}
# Move the attachment into holding directory.
eval { writefile($file, $config{srcdir}, $content) };
$config{cgi}=1;
if ($@) {
eval { writefile($file, $config{srcdir}, $content) };
$config{cgi}=1;
if ($@) {
+ # save $@ in case a called function clobbers it
+ my $error = $@;
$form->field(name => "rcsinfo", value => rcs_prepedit($file),
force => 1);
my $mtemplate=template("editfailedsave.tmpl");
$form->field(name => "rcsinfo", value => rcs_prepedit($file),
force => 1);
my $mtemplate=template("editfailedsave.tmpl");
- $mtemplate->param(error_message => $@);
+ $mtemplate->param(error_message => $error);
$form->tmpl_param("message", $mtemplate->output);
$form->field("editcontent", value => $content, force => 1);
$form->tmpl_param("page_select", 0);
$form->tmpl_param("message", $mtemplate->output);
$form->field("editcontent", value => $content, force => 1);
$form->tmpl_param("page_select", 0);
$template=template("/".$template_page);
};
if ($@) {
$template=template("/".$template_page);
};
if ($@) {
+ # gettext can clobber $@
+ my $error = $@;
# Indicate that the earlier preprocessor directive set
# up a template that doesn't work.
# Indicate that the earlier preprocessor directive set
# up a template that doesn't work.
- return "[[!edittemplate ".gettext("failed to process template:")." $@]]";
+ return "[[!edittemplate ".gettext("failed to process template:")." $error]]";
}
$template->param(name => $page);
}
$template->param(name => $page);
blind_cache => 1);
};
if ($@) {
blind_cache => 1);
};
if ($@) {
- error sprintf(gettext("failed to process template %s"), $params{template}.".tmpl").": $@";
+ # gettext can clobber $@
+ my $error = $@;
+ error sprintf(gettext("failed to process template %s"), $params{template}.".tmpl").": $error";
}
}
my $needcontent=$raw || (!($archive && $quick) && $template->query(name => 'content'));
}
}
my $needcontent=$raw || (!($archive && $quick) && $template->query(name => 'content'));
$markdown_sub=\&Markdown::Markdown;
}
else {
$markdown_sub=\&Markdown::Markdown;
}
else {
do "/usr/bin/markdown" ||
do "/usr/bin/markdown" ||
- error(sprintf(gettext("failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"), $@, $!));
+ error(sprintf(gettext("failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"), $error, $!));
$markdown_sub=\&Markdown::Markdown;
}
}
$markdown_sub=\&Markdown::Markdown;
}
}
blind_cache => 1);
};
if ($@) {
blind_cache => 1);
};
if ($@) {
+ # gettext can clobber $@
+ my $error = $@;
error sprintf(gettext("failed to process template %s"),
htmllink($params{page}, $params{destpage},
error sprintf(gettext("failed to process template %s"),
htmllink($params{page}, $params{destpage},
- "/templates/$params{id}"))." $@";
+ "/templates/$params{id}"))." $error";
}
$params{basename}=IkiWiki::basename($params{page});
}
$params{basename}=IkiWiki::basename($params{page});