Ad. 1. Yes and no - [there are still some pitfalls][1] (please read further). Ad. 2. You must remember about returning truthy value from `eval` block because it evaluates to last value in block **unless** some code died, in which case `undef` is returned, so `1;` as last statement in `eval` block is important. You also have to localize `$@` somehow (`my $error = $@` in your example) because it's a global variable which can be changed silently (see Conclusion). Ad. 3. `if ($@)` can have one pitfall, i.e. it doesn't catch error when it's false: eval { die ''; do_something(); }; if ($@) { # ooops... we don't get here } while `or do { }` block will always be activated in case of exception eval { die ''; do_something(); 1; } or do { # caught! }; **Conclusion:** I personally use "eval or do # process error" style of catching errors but common and widely used alternative, which eleminates boilerplate code, is to use [`Try::Tiny`][2]. It's a simple, 0-dependency CPAN module which addresses `$@` issues. Its documentation (especially BACKGROUND section) is really worth reading as it answers some of your questions and with even more details. See also [this SO question][3]. [1]: https://metacpan.org/module/Try::Tiny#BACKGROUND [2]: https://metacpan.org/module/Try::Tiny [3]: https://stackoverflow.com/questions/10364975/is-trytiny-still-recommended-for-exception-handling-in-perl-5-14-or-later