Smoke-test a Perl 5.38 upgrade before shipping code
You will finish with a small set of checks for a Perl 5.38 installation: confirm the interpreter version, exercise the new experimental class syntax, prove that PERL_RAND_SEED makes an unseeded random sequence repeatable, and expose deprecation warnings that may affect older code. Allow about 15 minutes for the checks, plus time to run your own application's tests.
The route
Jump straight to the step you need, or tick off Done means at the end.
The local manual page describes the change from Perl 5.36.0 to 5.38.0. The installed interpreter here is Perl v5.38.2, built for x86_64-linux-gnu-thread-multi. Patch releases can differ in details, so record the exact result from your own machine before comparing it with a deployment host.
1. Record the interpreter you are testing
Start with a read-only version check. Run it as the same account that will run the application; do not use sudo merely to inspect Perl.
$ perl -v
This is perl 5, version 38, subversion 2 (v5.38.2) built for x86_64-linux-gnu-thread-multi
$ perl -V:version -V:archname
version='5.38.2';
archname='x86_64-linux-gnu-thread-multi';
Your patch level and architecture may be different. Stop here if the service's interpreter is not the one you intended to upgrade. A shell's PATH can select a different Perl from the one used by a service, so check the service's launch environment separately.
Checkpoint
Save the version and architecture with the application's test report. This gives a useful comparison if a later failure only occurs on one host.
2. Exercise the new class syntax in isolation
Perl 5.38 adds an experimental class feature. A class can declare per-instance field variables and methods. This is not a stable replacement for an established object system: the manual says the feature remains experimental and warns in the experimental::class category.
Put the following in a temporary file or pass it to perl -e. The example creates an object, changes both fields through a method and prints a result. The no warnings line is deliberate and local to this experiment.
$ perl -e 'use feature "class"; no warnings "experimental::class"; class Point { field $x; field $y; method zero { $x = $y = 0 } }; my $p = Point->new; $p->zero; print "class-ok\n"'
class-ok
Keep experimental warnings enabled in normal development unless you have reviewed and accepted the feature. Suppressing them globally can hide a future compatibility warning. To see the warning on this interpreter, remove no warnings "experimental::class" and run the same compile check.
$ perl -we 'use feature "class"; class Point { field $x; method zero { $x = 0 } }'
class is experimental at -e line 1.
field is experimental at -e line 1.
method is experimental at -e line 1.
The exact line numbers and warning ordering are not an interface. The useful result is that the code compiles on the target interpreter and that the warnings are visible when you have not opted out.
3. Test repeatable random output without changing application code
Perl 5.38 introduces PERL_RAND_SEED. It can make code that calls rand without an explicit seed, or calls srand without an argument, repeatable. This is useful for a focused test run. It is not a source of secrets or a substitute for a cryptographic random generator.
Run the same short program twice with the same environment value, then once with a different value:
$ PERL_RAND_SEED=12345 perl -e 'print join(" ", map { rand() } 1..3), "\n"'
0.225328512796299 0.919183068533556 0.206841253248182
$ PERL_RAND_SEED=12345 perl -e 'print join(" ", map { rand() } 1..3), "\n"'
0.225328512796299 0.919183068533556 0.206841253248182
$ PERL_RAND_SEED=54321 perl -e 'print join(" ", map { rand() } 1..3), "\n"'
0.0230370595390958 0.808510160629766 0.197774572801915
Compare complete output in a test, rather than copying these particular numbers into a portability test. The sequence is tied to Perl's implementation and version. Never set this variable in a production process that needs unpredictable values, and do not mistake repeatability for security.
4. Turn deprecations into actionable test failures
Perl 5.38 gives deprecation warnings specific subcategories. Smartmatch is the obvious upgrade trap: its experiment was declared a failure in this release and the manual says the feature is planned for removal in Perl 5.42. Existing code using ~~ can still run in 5.38, but it should be found and replaced rather than hidden.
$ perl -we 'my $same = 1 ~~ 1; print "same=$same\n"'
Smartmatch is deprecated at -e line 1.
same=1
For a codebase, make warnings visible during the test command and search source and generated code for the operator:
$ rg --glob '*.pl' --glob '*.pm' '~~' lib bin t
$ PERL5OPT=-Mwarnings prove -lr t
Do not edit every match mechanically. Smartmatch has context-dependent behaviour, so replace each use with the comparison that expresses its intended types and data shape. Treat the warning as a review queue, not as permission to disable the deprecated category.
5. Check the 5.38 I/O compatibility edge
There is one change worth adding to tests that reuse filehandles. In 5.38, readline(), also written as <>, normally leaves the stream's error and end-of-file flags set after an error or end of input. If code binds the handle to another descriptor or expects to read again, call $handle->clearerr() at the deliberate recovery point.
This is especially relevant to modules using non-blocking descriptors. A failed read can set the error flag, and a later close() can then fail or warn. Check the return values from both operations and test the recovery path with the same descriptor type used in production. Do not add clearerr() blindly after every read: clearing a real error can discard information your caller needs.
The other compatibility changes in the manual include earlier compile-time rejection of forbidden control flow out of defer or finally, and fewer follow-on diagnostics after a syntax error. A failed compile is therefore not evidence that every old diagnostic should still appear. Assert success or failure and the useful part of the diagnostic, not a whole historical error transcript.
Done means
- The test report records the exact Perl version and architecture used by the target process.
- The experimental class check compiles, and any warning suppression is explicit and local.
- The same
PERL_RAND_SEEDproduces the same sequence in a test process, while a different seed changes it. - Smartmatch and other deprecation warnings are visible in the test run and have an owner for replacement.
- Code that reuses filehandles after EOF or read errors has a deliberate
clearerr()recovery test. - No upgrade check required root, changed a service, or changed production data.