fix: POSIX :fcntl_h seek constants + cleaner Java-exception error reporting#539
Merged
fix: POSIX :fcntl_h seek constants + cleaner Java-exception error reporting#539
Conversation
The POSIX :fcntl_h export tag was missing the seek constants. Real perl's POSIX exports SEEK_SET/SEEK_CUR/SEEK_END under :fcntl_h, and modules like File::Slurp rely on this (use POSIX qw(:fcntl_h) then use SEEK_SET as a bareword). Without this, File::Slurp fails at runtime with: Bareword "SEEK_SET" not allowed while "strict subs" in use which breaks any module depending on File::Slurp (IO::Any, etc.). Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
When a Java exception leaks through to the CLI reporter, users were
sometimes shown two cryptic lines:
java.lang.NoClassDefFoundError: org/perlonjava/runtime/operators/KillOperator
org.perlonjava.runtime.operators.KillOperator
<perl stack trace>
This happens in two scenarios:
- A wrapping exception's message is set from Throwable.toString() of the
inner cause ("java.lang.Foo: message"), so both the wrapper and the
inner print.
- NoClassDefFoundError wraps ClassNotFoundException for the same class;
the two differ only in slash vs dot separators.
ErrorMessageUtil.stringifyException now:
- Suppresses the outer message when it is literally Throwable.toString()
of an ancestor in the cause chain, or when it differs only in / vs .
from that ancestor's message (isJavaToStringOf).
- Strips a leading fully-qualified Java exception class prefix
("java.lang.X: ...") from whatever message remains, so users see the
actual description instead of JVM class names
(stripJavaExceptionPrefix).
Perl-style messages (single-word package, trailing newline suppression,
etc.) pass through unchanged. Added ErrorMessageUtilTest covering
happy-path Perl messages, wrapped Java errors, and the slashed/dotted
duplicate case.
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two small, independent runtime/stdlib fixes surfaced while investigating
jcpan -t IO::Any.POSIX :fcntl_hnow exportsSEEK_SET/SEEK_CUR/SEEK_ENDReal perl's
POSIX :fcntl_hexports these; ours did not. Modules that douse POSIX qw(:fcntl_h)and then useSEEK_SETas a bareword — notablyFile::Slurp— die at runtime withBareword "SEEK_SET" not allowed while "strict subs" in use at File/Slurp.pm line 119, which cascades intoIO::Any,Config::Simple, and anything else pulling inFile::Slurp.CLI reporter no longer surfaces raw Java exception class names
When a Java exception leaked through to the reporter, users would sometimes
see two cryptic Java-looking lines above the real message:
Two causes:
inner.toString()("java.lang.Foo: msg") caused both the wrapper and the inner message to
print.
NoClassDefFoundError(slash-separated) commonly wrapsClassNotFoundException(dot-separated) for the same class; the twodiffer only in
/vs.and were treated as independent messages.ErrorMessageUtil.stringifyExceptiongains two helpers:isJavaToStringOf(outer, inner)— suppresses the outer line when it isliterally
Throwable.toString()of any ancestor in the cause chain, ordiffers only in
/vs.from an ancestor's message.stripJavaExceptionPrefix(message)— strips a leading fully-qualifiedJava exception class prefix (
java.lang.X: …,org.foo.YException: …).The pattern requires a dotted prefix with at least two segments plus
a recognizable
Exception/Error/Throwablesuffix, so legit Perlmessages like
"DBI error: handle closed"or"Foo: not a java class"pass through unchanged.
Impact on
jcpan -t IO::Anyt/01_IO-Any.tt/02_IO-Any_AnyEvent.tt/03_DATA.tRemaining failures are unrelated to this PR:
t/01_IO-Any.ttest 30 is a non-blocking shared-lock assertion that hitsEDEADLKon macOS — flock emulation quirk.t/02_IO-Any_AnyEvent.ttimes out because AnyEvent::Loop's I/O watchersare destroyed on return (a
push @q, $self; weaken $q[-1]refcount issuethat is being addressed on a separate refcount branch).
Test plan
ErrorMessageUtilTestwith 5 cases (wrapped NCDF, slashed/dotteddedup, Perl pass-through, false-positive
Foo: barstrings).make— full unit test suite green.jcpan -t IO::Anybefore/after; output diff above.Generated with Devin