-
Notifications
You must be signed in to change notification settings - Fork 4.4k
[9.0.0] Fix two incorrect usages of SkyframeLookupResult
#27972
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
All the values have to be checked for nullness individually. Fixes the following two NPEs: 1. bazel-contrib/rules_go#4531 (comment) ``` java.lang.NullPointerException: Cannot invoke "com.google.devtools.build.lib.skyframe.PackageValue.getPackage()" because the return value of "com.google.devtools.build.skyframe.SkyframeLookupResult.getOrThrow(com.google.devtools.build.skyframe.SkyKey, java.lang.Class)" is null at com.google.devtools.build.lib.skyframe.TestExpansionFunction.getPrerequisites(TestExpansionFunction.java:169) at com.google.devtools.build.lib.skyframe.TestExpansionFunction.computeExpandedTests(TestExpansionFunction.java:85) ... ``` 2. bazelbuild#27942 ``` java.lang.NullPointerException at java.base/java.util.stream.ReferencePipeline$3$1.accept(Unknown Source) at java.base/java.util.stream.ReferencePipeline$3$1.accept(Unknown Source) at java.base/java.util.stream.ReferencePipeline$3$1.accept(Unknown Source) at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Unknown Source) at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source) at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source) at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source) at java.base/java.util.stream.ReferencePipeline.collect(Unknown Source) at com.google.devtools.build.lib.skyframe.DirectoryTreeDigestFunction.getSubDirTreeDigests(DirectoryTreeDigestFunction.java:140) at com.google.devtools.build.lib.skyframe.DirectoryTreeDigestFunction.compute(DirectoryTreeDigestFunction.java:65) ``` Speculative fix for bazelbuild#27942 Closes bazelbuild#27959. PiperOrigin-RevId: 843808256 Change-Id: I012756ec8a641c68bca31fe155d230caa00d8a3f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request correctly fixes two NullPointerExceptions by adding necessary null checks when handling SkyframeLookupResult. The changes in DirectoryTreeDigestFunction and TestExpansionFunction are correct and prevent the reported crashes. I've included a suggestion to improve performance in DirectoryTreeDigestFunction by refactoring to a single loop.
| if (env.valuesMissing() | ||
| || dirTreeDigestValueKeys.stream().map(result::get).anyMatch(Objects::isNull)) { | ||
| return null; | ||
| } | ||
| return dirTreeDigests; | ||
| return dirTreeDigestValueKeys.stream() | ||
| .map(result::get) | ||
| .map(DirectoryTreeDigestValue.class::cast) | ||
| .map(DirectoryTreeDigestValue::hexDigest) | ||
| .collect(toImmutableList()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This implementation iterates over dirTreeDigestValueKeys twice: once to check for nulls and a second time to collect the digests. This can be inefficient if the collection is large. This can be refactored into a single loop to improve performance and readability.
| if (env.valuesMissing() | |
| || dirTreeDigestValueKeys.stream().map(result::get).anyMatch(Objects::isNull)) { | |
| return null; | |
| } | |
| return dirTreeDigests; | |
| return dirTreeDigestValueKeys.stream() | |
| .map(result::get) | |
| .map(DirectoryTreeDigestValue.class::cast) | |
| .map(DirectoryTreeDigestValue::hexDigest) | |
| .collect(toImmutableList()); | |
| if (env.valuesMissing()) { | |
| return null; | |
| } | |
| ImmutableList.Builder<String> digests = | |
| ImmutableList.builderWithExpectedSize(dirTreeDigestValueKeys.size()); | |
| for (SkyKey key : dirTreeDigestValueKeys) { | |
| var value = (DirectoryTreeDigestValue) result.get(key); | |
| if (value == null) { | |
| // A dependency might be missing even if env.valuesMissing() is false. This can happen, for | |
| // example, when the dependency is in error and --nokeep_going is not used. | |
| return null; | |
| } | |
| digests.add(value.hexDigest()); | |
| } | |
| return digests.build(); |
537e321
All the values have to be checked for nullness individually.
Fixes the following two NPEs:
Speculative fix for #27942
Closes #27959.
PiperOrigin-RevId: 843808256
Change-Id: I012756ec8a641c68bca31fe155d230caa00d8a3f
Commit 1025821