October 20, 2017·4 min read·engineeringperlprocessescorrectness

Perl 5.27.5 passes empty exec arguments to execvp

An explicit program with an empty argument list must still reach the process execution call. Perl 5.27.5 fixes an early false return that also left the error variable unset.

Naming an executable and supplying its argument vector are separate operations in Perl's explicit exec form. Perl 5.27.5 fixes a case where an empty argument list prevented the execution call altogether. The interpreter returned false without setting $!, leaving the caller without the normal explanation for a failed attempt. The release notes say this form should call execvp() with an array containing only its terminating null pointer. Its release history dates the snapshot to October 20, 2017.

The correction is to the boundary between Perl and the execution function. It does not promise that every operating system or target program accepts an empty argument vector. It makes the requested attempt reach the underlying operation, instead of treating the empty list as a reason to return without one.

I value direct process calls in small utility programs because their argument handling can remain visible in the source. This fix matters to that clarity. An explicit request should reach the documented operation, and an unsuccessful call should have a meaningful error path.

The program name need not be the first argument

The function documentation for this release describes exec PROGRAM LIST. In this form the caller names the program separately from the list passed to it. The distinction allows the program to receive a different apparent name as its first argument, as in the documented login-shell example.

Braces make the separation explicit. The documentation uses an array-based form:

my @args = ("echo surprise");
exec { $args[0] } @args;

This attempts to execute a program whose name is literally echo surprise. It does not run echo with surprise as its argument. That example demonstrates why specifying the program changes the interpretation even when the list contains only one element.

The empty-list repair follows the same separation. A caller can identify PROGRAM while providing no argument entries. Perl must not confuse the absence of list elements with the absence of an executable selection. The release specifies the resulting C-level vector as containing just the terminating null pointer.

One scalar can otherwise invoke shell rules

Without the explicit program form, exec treats a single list element differently. The documentation says it checks the string for shell metacharacters. If those are present, it passes the string to the system shell. Otherwise, it splits the string into words and passes them directly to execvp.

That means a wrapper whose array sometimes has one element can change interpretation with its input. The number of entries affects whether Perl treats the request as an argument list or a string requiring further processing. The explicit program form always forces multivalued-list interpretation, including when the list has only one scalar.

The Windows qualification is also explicit. Only exec PROGRAM LIST reliably avoids using the shell there. A plain exec LIST, even with multiple elements, may fall back to the shell after the initial spawn fails. A claim that all multi-argument calls avoid the shell on every supported platform would therefore be wrong for this documented interface.

These distinctions concern execution semantics, not merely quoting style. Selecting the executable separately can preserve an argument containing whitespace as a single entry. The October correction makes the empty-vector boundary consistent with that explicit separation, while the platform still determines the eventual execution result.

Successful exec does not resume the caller

The documentation describes exec as abandoning the current program to run another. A caller that needs to resume after the child finishes should use system. Treating exec as a normal call that returns a successful status would misunderstand its control flow.

Failure is therefore the reason to inspect code following the call. The old empty-list behavior was troublesome because it manufactured a false return without setting the error variable. That result did not describe an actual failed execvp attempt, so ordinary error reporting could lack the relevant explanation.

The same documentation says exec does not call END blocks or invoke object destructors. It attempts to flush open output files first, with platform qualifications. A wrapper that relies on language cleanup after successful replacement needs to account for that contract. The new fix changes the previously skipped attempt, not those cleanup semantics.

I prefer keeping such wrappers small enough that the program selection and control flow can be read together. A clear failure branch after exec is easier to interpret when the interpreter consistently distinguishes an operating-system failure from a request it never attempted.

Other corrections restore explicit contracts

The release also makes splice throw an exception when asked to modify a read-only array. Previously it silently modified the array. The corrected behavior matches push and unshift, so choosing a different array operation no longer evades the read-only restriction in this case.

Another fix concerns constant lookup through the internal gv_fetchmeth_sv function. Constants with UTF-8 names had failed when stored as simple scalar references instead of full typeglobs, a regression dating to Perl 5.22. Correcting that path restores lookup for the particular internal representation. Together, these changes address places where the implementation had failed to honor the operation already expressed by the caller.