fix: portable errno constants (ELOOP, ENOTEMPTY) + WRITE validation#210
fix: portable errno constants (ELOOP, ENOTEMPTY) + WRITE validation#210Koan-Bot wants to merge 3 commits intocpanel:masterfrom
Conversation
|
View failures from CI pipeline |
Rebase: fix: portable errno constants (ELOOP, ENOTEMPTY) + WRITE validationBranch Actions
Automated by Kōan |
|
|
||
| unless ( $len =~ m/^-?[0-9.]+$/ ) { | ||
| $! = qq{Argument "$len" isn't numeric in syswrite at ??}; | ||
| CORE::warn(qq{Argument "$len" isn't numeric in syswrite at @{[ join ' line ', (caller)[1,2] ]}.\n}); |
There was a problem hiding this comment.
The old code $! = qq{Argument "$len" isn't numeric...} has two problems:
-
$!is errno, not a string — assigning a string to$!is semantically wrong.$!expects a numeric errno value (EINVAL, EBADF, etc.), and its string form comes fromstrerror(). Assigning arbitrary strings produces unpredictable behavior when callers check$! == EINVAL. -
Real Perl emits a warning —
syswrite($fh, "buf", "not_a_number")producesArgument "not_a_number" isn't numeric in syswrite at ... line N.on STDERR. Same for negative length and offset-outside-string. These are warnings, not silent errno changes.
CORE::warn() matches real Perl behavior. The (caller)[1,2] replaces the hardcoded ??? placeholders with actual file/line info.
Alternative: we could use Carp::carp for consistency with the rest of the module, but CORE::warn is closer to what Perl itself does internally. Happy to adjust if you prefer a different approach.
There was a problem hiding this comment.
@Koan-Bot but perl sets $! in these cases and you've just removed that behavior. I'm fine that we were setting it wrong but not setting it at all is a problem.
7deae76 to
e6b184b
Compare
|
CI is now green across all 18 Perl versions (5.10 through 5.42). The fix: changed |
|
Note: this branch needs a rebase — the diff currently reverts PRINT improvements that were merged via PRs #199 (tell position) and the Regarding the
Happy to adjust either way. What's your preference? |
e6b184b to
366890f
Compare
366890f to
466671b
Compare
Replace hardcoded errno numbers with portable POSIX constants: - $! = 40 → $! = ELOOP in __sysopen (O_NOFOLLOW on symlink) - $! = 39 → $! = ENOTEMPTY in __rmdir (non-empty directory) These values differ across platforms (Linux ELOOP=40, macOS=62; Linux ENOTEMPTY=39, macOS=66), causing incorrect errno on non-Linux. Also fix FileHandle.pm WRITE method: - String assignments to $! replaced with proper warn/die - Negative length now dies (matches real syswrite behavior) - Offset outside string now dies (matches real syswrite) - Fix offset validation order: convert negative offset before bounds check (previously, too-negative offsets silently passed) Co-Authored-By: Claude Opus 4.6 <[email protected]>
466671b to
a719137
Compare
Rebase: fix: portable errno constants (ELOOP, ENOTEMPTY) + WRITE validationBranch Actions
Automated by Kōan |
Summary
Errnoconstants:$! = 40→$! = ELOOPin__sysopen(O_NOFOLLOW on symlink)$! = 39→$! = ENOTEMPTYin__rmdir(non-empty directory)FileHandle::WRITEerror handling to match realsyswritebehavior:warninstead of assigning string to$!die(fatal, like real syswrite)die(fatal, like real syswrite)Motivation
Errno values differ across platforms:
Hardcoding Linux values means incorrect
$!on macOS/FreeBSD.The
WRITEmethod was assigning error message strings to$!, which is incorrect —$!expects a numeric errno or a system error string that maps to one. Realsyswriteuseswarn/diefor these error conditions.The offset validation bug meant
syswrite($fh, "hello", 2, -10)silently proceeded instead of dying with "Offset outside string" (offset -10 on a 5-char string is invalid).Test plan
t/portability_errno.twith 7 subtests covering ELOOP, ENOTEMPTY, and WRITE error casest/rmdir.tto useENOTEMPTYconstant instead of hardcoded39🤖 Generated with Claude Code