pperl 0.6.9#

2026-07-28 to 2026-08-05, 211 commits.

Language and runtime#

  • SIGPIPE stops a program whose output pipe was closed, as on perl5: pperl generate.pl | head ran forever. pperl keeps the SIGPIPE disposition it was started with instead of ignoring the signal, so the exit status is 141, and $SIG{PIPE} handlers and $SIG{PIPE} = 'IGNORE' behave as on perl5.

  • $0: assigning to it, as cpanm and Starman do to label their processes, no longer crashes pperl or writes into unrelated memory. The assignment changes the process’s command line as ps and /proc/self/cmdline show it, also for names longer than the original command line, so Starman’s renamed workers can be told apart.

JIT and parallelization#

  • mandelbrot: the Benchmarks Game’s mandelbrot, with its thread pool replaced by a plain loop over scanlines and its kernel unchanged, now runs its kernel compiled; before, the kernel never compiled. At size 2000 it takes 0.62 s of CPU time on one core, against 4.96 s wall-clock and 19.7 s CPU time for the published four-thread entry on perl5.

  • Loops that now compile: for (LIST) with the implicit $_ compiles, as do next LABEL and last LABEL aimed at an enclosing compiled loop, and a for loop over an array nested in another compiled loop, which now compiles together with it. A loop body may begin with my $x; or my ($a, $b);, assign a list such as my ($a, $b) = (0, 0), and append with .= to a variable declared without a value; each of these kept the loop from compiling.

  • Element updates: the assignment operators +=, -=, *=, /=, |=, &=, ^=, <<= and >>= and the operators ++ and -- compile on array and hash elements and on elements reached through references, such as $m[$i][$j] += $x, also when the index is computed, as in $a[$i + 1] or $a[$i % 2]. sqrt compiles too.

  • Subroutines called from compiled loops compile together with the loop also when they use arrays, hashes or strings, use package variables, or assign to a my variable they close over, as in my $acc; sub add { $acc += $_[0] }. Arguments read through @_ or as $_[0] compile, also in a sub that never copies them, such as sub f { $_[0] * $_[1] }, and a call with literal arguments such as f(3, 5) no longer keeps its loop from compiling.

  • Wrong results in compiled loops: a nested range loop whose body assigns its loop variable or whose lower bound is an expression, a sub assigning to $_[0], and a sub adding to a variable it closes over could abort or give wrong results in compiled code. They now give perl5’s results.

Modules#

  • Encode provides all 124 encodings of the upstream distribution, up from 21: the single-byte tables generated from the Unicode mapping data, UTF-16, UTF-32 and UCS-2, the 21 multi-byte CJK encodings, ISO-2022, gsm0338, hz, UTF-7 and the MIME encoded-word codecs. Each was checked against perl5’s Encode, the CJK tables over every two-byte sequence. Names resolve through upstream’s alias rules, so windows-1252, latin2, sjis or macintosh work without a perl5 installation, and Encode->encodings lists the loaded encodings until ":all" is asked for.

  • Encode error handling: the CHECK argument of encode, decode and from_to is honoured. FB_CROAK dies, FB_PERLQQ, FB_HTMLCREF and FB_XMLCREF substitute escapes, and FB_QUIET and FB_WARN return what was converted and leave the rest in the source variable, as on perl5; before, every mode behaved as the default. The UTF-16 and UTF-32 encodings report surrogates, noncharacters and partial characters with perl5’s messages.

  • :encoding layers no longer replace a character that straddles a read buffer boundary with U+FFFD; a 6 KiB file of three-byte characters lost characters at three places. :encoding(UTF-16LE), :encoding(koi8-r) and the other new encodings work for reading and writing, $PerlIO::encoding::fallback is reset on the layer’s first use as on perl5, and require PerlIO::encoding at run time no longer dies with “Out of memory during stack extend”.

  • Storable writes and reads perl5’s format byte for byte: an image stored by perl5 retrieves on pperl and the other way round, and with $Storable::canonical both write identical bytes. Hooks (STORABLE_freeze, STORABLE_thaw, STORABLE_attach), code references, regexps, tied and restricted hashes, weak references and images written by Storable versions before 0.7 are handled, and the module’s Perl half is upstream’s Storable.pm. Storable’s own test suite passes all 2,728 assertions it passes on perl5. Freezing a tied hash stored none of its keys; it now stores the tie object, as perl5 does.

  • Thawing untrusted data: a Storable image whose class name was crafted Perl code ran that code when it was thawed; class methods are now looked up without compiling anything. A truncated image returns undef without setting $@, a corrupt one croaks with perl5’s message, and an image that blesses a file name into CGITempFile warns as perl5 does (CVE-2015-1592).

  • POSIX: use POSIX; imports POSIX’s default export list; it imported nothing, so floor, INT_MAX or WIFEXITED had to be fully qualified, and Test::TCP did not install. The functions perl5 implements in Perl, such as POSIX::localtime and POSIX::stat, exist, C-only names such as POSIX::malloc croak with perl5’s advice, use POSIX qw(locale_h) works, and a call with the wrong number of arguments croaks with perl5’s usage message where POSIX::abort(1,2,3) aborted and POSIX::_exit(1,2,3) exited. perl5’s own POSIX test suite gives the same results on pperl, all 4,514 assertions.

  • POSIX time functions: POSIX::strftime derives the weekday, the day of the year, daylight saving time and the UTC offset from the date instead of trusting optional arguments; called with six fields, %a, %j, %V, %z and %Z were wrong. POSIX::strftime::Compiler, which Plack and Starman depend on, now installs with --cpan. strftime no longer cuts its result at 1024 bytes, asctime accepts six arguments, ctime honours $ENV{TZ}, and difftime truncates its arguments to integers as perl5 does.

  • POSIX signals: POSIX::SigAction and POSIX::SigRt exist, so sigaction works in its documented form, with a code reference as handler, a signal name such as "INT", and the SAFE flag as perl5 reports it. sigaction given an array or scalar reference instead of a POSIX::SigAction crashed the interpreter, and one that croaked left signals blocked; both now behave as on perl5. POSIX::SigSet objects check their arguments, addset(-1) croaks, and can be subclassed.

  • POSIX constants: the 16 terminal speed constants such as B9600 had wrong values (13 instead of 9600), and FP_NAN, FP_INFINITE, FP_ZERO and FP_NORMAL were permuted, so fpclassify(0.0) returned 4 instead of 2. ULONG_MAX is exact, MB_CUR_MAX follows the locale, FLT_ROUNDS follows fesetround, and ARG_MAX, LDBL_EPSILON, LDBL_MAX and LDBL_MIN croak as on perl5 instead of returning approximations. POSIX gained 104 constants and re-exports Fcntl’s record-locking constants F_GETLK, F_SETLK and F_SETLKW.

  • POSIX locale: under a locale such as de_DE.UTF-8, POSIX::strtod("3,5") returns 3.5, localeconv() reports the locale’s separators, and setlocale(LC_ALL) returns the locale’s name, as on perl5. localeconv returns all 24 keys, with -1 for fields the locale leaves unspecified, and mblen, mbtowc and wctomb answer as perl5’s do at the edges, mblen("") being 0.

  • POSIX arguments and results: POSIX functions read arguments that come from a regex capture or a tied variable; POSIX::floor($1) returned 0. Functions perl5 declares as returning a system result, such as sysconf, mkfifo and setuid, give undef on failure and “0 but true” for zero, so defined(mkfifo(...)) or die works. strtol and strtoul accept the 0b prefix, strtoul returns values above the signed range, strtod in scalar context returns the number, and the POSIX::Termios speed setters accept a baud rate.

  • DBD::SQLite is a new driver over the system’s libsqlite3. It passes 98 of the 103 test files of DBD::SQLite 1.78’s own suite and supports user-defined functions, aggregates and collations, the commit, rollback, update and authorizer hooks, online backup, the catalogue methods and the fts3 Perl tokenizer. Values bind and fetch with the storage class and bytes upstream’s driver gives them, strings with embedded NUL bytes included, and SQL that issues its own BEGIN works.

  • DBD::Pg supports PostgreSQL arrays in both directions, COPY through pg_putcopydata and pg_getcopydata as well as pg_putline and pg_getline, savepoints, asynchronous queries (pg_async, pg_ready, pg_result, pg_cancel), cancel, bind_param_inout and pg_enable_utf8. It exports the PG_* type constants, where use DBD::Pg ':pg_types' died, and reports PRECISION, SCALE, NULLABLE, ParamValues, ParamTypes, pg_lib_version and the type names in pg_type as upstream’s driver does.

  • DBD::Pg placeholders and quoting: quote honours its type argument, so quote(3.14, SQL_FLOAT) is unquoted and an invalid float dies, and identifiers that are reserved words are quoted. A placeholder written \? stays a literal ? operator, :1 and binding by name (bind_param('$1', ...)) work, pg_placeholder_dollaronly and pg_placeholder_nocolons are honoured, and an array slice arr[1:2] is not taken for a placeholder. do without bind values sends the statement unchanged, statements such as SET search_path TO ? run with placeholders, and only bytea parameters are sent in binary form; an integer parameter beside a bytea one made the server reject the statement.

  • DBD::MariaDB is a new driver over libmariadb, and DBD::mysql is now a compatibility layer over it that keeps the dbi:mysql: names and the mysql_* attributes. Both gained asynchronous queries (async => 1, mysql_async_ready, mysql_async_result, mysql_fd), table_info, column_info, primary_key_info, foreign_key_info and statistics_info, the full get_info table, ChopBlanks, implicit reconnect and the numeric mysql_serverversion and mysql_clientversion. Placeholders inside comments and after LIMIT are handled as upstream’s driver handles them.

  • DBI: with InactiveDestroy set, DBD::Pg and DBD::MariaDB leave the connection open when a handle is destroyed, so a forked child no longer closes its parent’s connection. A true Taint attribute no longer croaks, NAME_hash is defined for a statement without columns, and the drivers’ $VERSION strings use upstream’s _01 form instead of a -pperl1 suffix that version checks could not parse.

  • Peta::FFI: Peta::FFI::closure turns a Perl code reference into a C function pointer that a C library can call, and closure_free releases it. A die in the Perl code does not unwind through the C caller.

  • HTTP::Parser::XS is native, with the same results as the 0.17 module on 26,000 differential cases; it is the parser Plack, Starman and Twiggy use. On input where scanning dominates it is 6.0 times as fast as the module on perl5, and as fast on a typical ten-header request.

  • Time::Piece: use Time::Piece works, where it died with a dynamic-loading error. Time::Piece 1.41’s Perl modules run on a native implementation of its compiled part, and the distribution’s own 15 test files pass, 1,142 assertions.

  • Term::ReadLine::Gnu provides all 160 functions of the 1.47 module’s compiled part and runs the distribution’s own Gnu.pm, embedded in pperl rather than taken from a perl5 installation. Perl callbacks such as completion_entry_function and those added with add_defun are called; before, they were stored and ignored.

  • glob: the built-in glob and <*.c> use File::Glob, as on perl5, instead of starting a shell for every call. Results no longer depend on the locale’s collation order, $File::Glob::DEFAULT_FLAGS is honoured, and 200 globs take about 10 ms instead of 520 ms. File::Glob’s constants have perl5’s values, bsd_glob sorts names differing only in case as perl5 does, and use File::Glob ':bsd_glob' replaces glob.

  • Socket has the 118 constants and seven functions it lacked, among them pack_ip_mreq and its relatives, without which joining a multicast group was impossible, and sockaddr_un. unpack_sockaddr_un validates its argument, the deprecated AI_IDN_* and NI_IDN_* constants croak as on perl5, and the :crlf tag exports $CR, $LF and $CRLF.

  • Fcntl has the record-locking constants F_GETLK, F_SETLK, F_SETLKW, F_RDLCK, F_WRLCK and F_UNLCK, and 48 more. A plain use Fcntl exports upstream’s 68 names, :Fcompat and :mode hold the right names, S_ENFMT and S_ISTXT are absent as on perl5 on Linux, and the S_IS* functions return perl5’s true and false values.

  • File::Temp: unlink0 compares the file handle with the path before deleting, so a file swapped in after creation is no longer removed, and the MEDIUM and HIGH safety levels are enforced instead of being treated as STANDARD. A File::Temp object keeps its file name and unlink flag in its glob, so ${*$fh} gives the name, and File::Temp::cleanup() no longer deletes the file of an object that is still alive.

  • Imports from native modules: overwriting a sub imported from a native module, as Net::Ping does with Socket’s SO_BINDTODEVICE, freed the module’s own sub and could crash the program later; imports now hold a reference, as on perl5. Import lists accept /pattern/ entries (use POSIX qw(/^S_I/)) and variables, and twelve native modules, among them Socket, Cwd and Scalar::Util, report perl 5.44’s module versions, so use Socket 2.041 works.

  • B has every method perl5’s B has, among them the B::REGEXP methods B::Deparse needs for a sub that uses a regexp, and B::COP::label, without which deparsed code lost its loop labels. B::OP->size returns the op’s size in bytes instead of its class number, B::hash and B::cstring give perl5’s results, and four list-returning methods such as B::AV::ARRAY no longer write past the stack and corrupt memory. B’s own test suite passes 535 of the 539 assertions it passes on perl5.

  • mro: an @ISA chain deeper than 100 classes no longer dies with “Recursive inheritance detected”; linearisations are cached as in perl5, and every depth measured, up to 500, behaves as on perl5. The C3 “Inconsistent hierarchy” error carries perl5’s merge trace, mro::get_linear_isa($class, 'dfs') honours its second argument and croaks on an unknown name, and a failing next::method names the method and the class.

  • Config: %Config has the extensions and static_ext keys, listing the native modules the binary contains, and answers 174 of perl5’s keys, up from 107. Test suites that check $Config{extensions} before running, as perl5’s own do, no longer skip themselves, and Config::config_re matches as perl5’s does.

  • Devel::Peek: DumpProg and runops_debug work, use Devel::Peek ':opd=stP' sets the debugging flags, and the module’s exports and variables, such as $D_flags and %EXPORT_TAGS, match perl5’s.

  • IO::Handle: ungetc accepts every code point perl5 accepts, including those above U+10FFFF, and treats negative and very large arguments as perl5 does; setbuf croaks only on output handles.

  • Data::Dumper, List::Util, Time::HiRes: print Dumper($x) printed its arguments before the dump, and Time::HiRes::stat in scalar context returned a wrong value; both behave as on perl5. List::Util::shuffle and sample follow srand, so srand(42) gives perl5’s permutation; shuffle returned the same order on every call, and sample could return its count argument.

  • Other native modules: Cwd::fast_realpath exists, Hash::Util::hash_seed returns the full 32-byte seed, and Hash::Util::bucket_ratio of an empty hash is 0. SDBM_File’s methods called with too few arguments croak with a usage message instead of crashing, and attributes::get finds the handler of a glob aliased from another package.

Command line#

  • Programs on standard input: pperl reads the program from standard input the three ways perl5 does, pperl < prog.pl, pperl - < prog.pl and pperl /dev/stdin < prog.pl, with $0 set as perl5 sets it. All three were refused.

  • --cpan: pperl --cpan MODULE... runs cpanm under pperl, installing into the library tree pperl searches, and --cpan --system installs into /usr/local/share/pperl. When building a distribution’s C part fails, it installs the pure-Perl files, which many such distributions fall back to, and names each distribution it did this for; Params::Validate installs and runs this way. Modules installed into ~/.pperl (or $PPERL_HOME) are found without setting PPERL5LIB.

  • Command-line switches: -- ends switch processing and is removed from the arguments, as on perl5; pperl listed it in its usage text but rejected it. Several -e or -E switches form one program, joined by newlines, where only the last one used to run, and the Makefiles ExtUtils::MakeMaker writes rely on both. With -e, a program argument that looks like a switch reaches @ARGV.

  • -I in option clusters: pperl -wIlib is -w plus -Ilib, as on perl5; it died with “Unknown option: -I”.

Documentation#

  • Translations: the catalogues of all 41 translation languages were brought up to date with the English pages for the first time since April, and the pages that had none, among them the CPAN tutorial, HTTP::Parser::XS and Time::Piece, are translated in every language. Slovak gained the complete perlfunc reference, and Hebrew and Greek the module reference, which raised them from 79.3% and 76.2% to 93.0% and 92.9%.

  • Translation fixes: 665 translated headings in all 41 languages that begin with a number, a dash, # or >, among them the numbered headings of the licence page, were displayed in English and now appear translated. Links to the perlfunc categories carry the translated category name, about 9,500 labels, and the line “Fully compatible with upstream Perl 5.44.” is translated again on the 217 perlfunc pages of 40 languages where it had fallen back to English.

  • CPAN tutorial: a new tutorial covers installing CPAN modules with pperl --cpan, the modules already built into pperl, how modules that need a C compiler are handled, and troubleshooting.

  • Module reference: 14 module descriptions on the index pages that were cut off mid-sentence, among them HTTP::Parser::XS, are complete, and the pages for IO::Handle, Time::HiRes, PerlIO::mmap and Data::Dumper show descriptions instead of implementation notes. List::Util::shuffle has its own page.

  • perlfunc reference: factual errors were corrected on the pages for abs, semop, shmget, send, crypt, getnetbyaddr, getservbyport, qq and exists; shmget now states that a key of 0 is IPC_PRIVATE.

  • How-to page: guides and tutorials are separate sections of cards, and the entry for programmers coming from other languages names every guide that exists, PHP, Ruby, Lua, sed, awk, shell and Tcl included.