Skip to content
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

Fix NullPointerException on a parallel run #35

Closed
wants to merge 1 commit into from

Conversation

jankratochvil
Copy link
Contributor

@jankratochvil jankratochvil commented Aug 17, 2022

Error: Unexpected exception occurred! java.lang.NullPointerException
java.lang.NullPointerException
	at com.sun.javatest.regtest.config.TestProperties$Cache.getEntryInternal(TestProperties.java:515)
	at com.sun.javatest.regtest.config.TestProperties$Cache.getEntryInternal(TestProperties.java:515)
	at com.sun.javatest.regtest.config.TestProperties$Cache.getEntry(TestProperties.java:502)
	at com.sun.javatest.regtest.config.TestProperties.getEntry(TestProperties.java:170)
	at com.sun.javatest.regtest.config.TestProperties.getTestNGRoot(TestProperties.java:123)
	at com.sun.javatest.regtest.config.RegressionTestFinder.scanFile(RegressionTestFinder.java:143)
	at com.sun.javatest.finder.TagTestFinder.scan(TagTestFinder.java:115)
	at com.sun.javatest.TestFinder.read(TestFinder.java:433)
	at com.sun.javatest.TRT_TreeNode.processFile(TRT_TreeNode.java:1259)
	at com.sun.javatest.TRT_TreeNode.scanIfNeeded(TRT_TreeNode.java:807)
	at com.sun.javatest.TRT_TreeNode.getTreeNode(TRT_TreeNode.java:616)
	at com.sun.javatest.TestResultTable.findNode(TestResultTable.java:400)
	at com.sun.javatest.TestResultTable.lookupNode(TestResultTable.java:533)
	at com.sun.javatest.TestResultTable.lookupInitURL(TestResultTable.java:571)
	at com.sun.javatest.TestResultTable.validatePath(TestResultTable.java:1000)
	at com.sun.javatest.regtest.config.TestManager.validatePath(TestManager.java:299)
	at com.sun.javatest.regtest.config.TestManager.getTests(TestManager.java:271)
	at com.sun.javatest.regtest.tool.Tool.createParameters(Tool.java:1659)
	at com.sun.javatest.regtest.tool.Tool.run(Tool.java:1293)
	at com.sun.javatest.regtest.tool.Tool.run(Tool.java:1082)
	at com.sun.javatest.regtest.tool.Tool.main(Tool.java:155)
	at com.sun.javatest.regtest.Main.main(Main.java:46)

Some debug output showing the problem:

	scanIfNeeded getRootRelativePath= separator=/ filesToScan[i]=resultdir
	processFile file=/resultdir isAbsolute=true
	TestFinder.java read file=/resultdir isAbsolute=true
	scanFile caller file=/resultdir
	scanFile File=/resultdir
	TestProperties.java:dir=/ rootDir=/home/azul/azul/zulu11-git/test/hotspot/jtreg file2=/resultdir file2.getParentFile()=/
	TestProperties.java:dir=null rootDir=/home/azul/azul/zulu11-git/test/hotspot/jtreg file2=/resultdir file2.getParentFile()=/

This happens with jtreg using -w:resultdir . getRootRelativePath() returns empty "" path. Other option would be to return "." but in such case it broke some other code.

This problem does not happen during a single run. It happens only when jtreg is being run in parallel, in my case:

	seq 1 100000|xargs -n1 -P64 ./runtest
	#! /bin/bash
	dir=result-test$$
	rm -rf $dir
	mkdir $dir
	set -o pipefail
	(JAVA_HOME=$HOME/azul/zulu11-git/build/linux-x86_64-normal-server-release/images/jdk/; $JAVA_HOME/bin/java -classpath $HOME/azul/jtreg/build/images/jtreg/lib/jtreg.jar:$HOME/azul/jtreg/build/images/jtreg/lib/javatest.jar:$HOME/azul/jtreg/build/images/jtreg/lib/asmtools.jar com.sun.javatest.regtest.Main -testjdk:$JAVA_HOME -othervm -verbose -ignore:quiet -retain:all -a -conc:1 -timeout:10 -vmoptions:-XX:+UnlockExperimentalVMOptions -w:$dir -noreport -dir:$JAVA_HOME/../../../../test/jdk/ -nativepath:$JAVA_HOME/../test/hotspot/jtreg/native ../hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking001/TestDescription.java |& tee $dir/err) || exit 255
	rm -rf $dir

Unforunately I am not yet Author so I do not yet have a JBS account so I cannot file it to JBS (Java Bug System).


Progress

  • Change must not contain extraneous whitespace

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jtharness pull/35/head:pull/35
$ git checkout pull/35

Update a local copy of the PR:
$ git checkout pull/35
$ git pull https://git.openjdk.org/jtharness pull/35/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 35

View PR using the GUI difftool:
$ git pr show -t 35

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jtharness/pull/35.diff

@bridgekeeper
Copy link

bridgekeeper bot commented Aug 17, 2022

👋 Welcome back jankratochvil! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Aug 17, 2022

@jankratochvil This change now passes all automated pre-integration checks.

After integration, the commit message for the final commit will be:

Fix NullPointerException on a parallel run

Reviewed-by: dbessono

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been no new commits pushed to the master branch. If another commit should be pushed before you perform the /integrate command, your PR will be automatically rebased. If you prefer to avoid any potential automatic rebasing, please check the documentation for the /integrate command for further details.

As you do not have Committer status in this project an existing Committer must agree to sponsor your change. Possible candidates are the reviewers of this PR (@dbessono) but any other Committer may sponsor as well.

➡️ To flag this PR as ready for integration with the above commit message, type /integrate in a new comment. (Afterwards, your sponsor types /sponsor in a new comment to perform the integration).

@openjdk openjdk bot added ready Pull request is ready to be integrated rfr Pull request is ready for review labels Aug 17, 2022
@mlbridge
Copy link

mlbridge bot commented Aug 17, 2022

Webrevs

@dbessono
Copy link
Collaborator

could it be a dup of https://bugs.openjdk.org/browse/CODETOOLS-7903229 ?

@jankratochvil
Copy link
Contributor Author

could it be a dup of https://bugs.openjdk.org/browse/CODETOOLS-7903229 ?

No, I have tried now that patch but it has no effect in this case.

Comment on lines 806 to 809
processFile(new File(TestResultTable.getRootRelativePath(this) +
File.separator + filesToScan[i]));
String path = TestResultTable.getRootRelativePath(this);
if (path != "")
path += File.separator;
processFile(new File(path + filesToScan[i]));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggested patch. I'd like suggest a bit more compact and direct, e.g.:

    String path = TestResultTable.getRootRelativePath(this);
    processFile(new File( "".equals(path) // Zero length string if the node is a root
                          ? filesToScan[i] : (path + File.separator + filesToScan[i]) ));

Comment on lines 807 to 808
processFile(new File( "".equals(path) // Zero length string if the node is a root
? filesToScan[i] : (path + File.separator + filesToScan[i]) ));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty ugly code, containing a complex expression inside the new File, and even path string computation instead of using a better File constructor.

I suggest something like:

processFile(path.isEmpty() // Zero length string if the node is a root
    ? new File(filesToScan[i]) 
    : new File(path, filesToScan[i]));

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if path is null ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, it might be better not to pull in an additional constructor that was not used before, but rather maximally stick with the existing code and APi calls it does

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If null is a possibility, check for it.

?? I don't understand the concern about referencing a different constructor that has been around since the beginning of Java time, and why it is better to do string arithmetic to construct a file path.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implicitly checking for null here below.
If we could keep the existing approaches and API calls in the legacy code base, let's not pull anything new without necessity. I guess we don't have necessity to call an API that is new to this context.

processFile("".equals(path) // Zero length string if the node is a root
    ? new File(filesToScan[i]) 
    : new File(path + File.separator + filesToScan[i]));

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If needed, refactoring like File constructors call optimizations deserves to be better done with a separate commit.

@jankratochvil
Copy link
Contributor Author

getRootRelativePath() can never return null:


The NullPointerException happens later in the code because the wrongly computed filename does not exist. (That could be an unrelated bug whether it should not be handled better, for example in the case someone deletes such file underneath.)

@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Sep 1, 2022
@dbessono
Copy link
Collaborator

dbessono commented Sep 1, 2022

@jankratochvil thanks for the update. I guess even if some method now doesn't return null, we'd be better prepared if it starts in future due to some refactoring.

Can see that the recent change failed jcheck

Check failure on line 808 in src/com/sun/javatest/TRT_TreeNode.java
openjdk / jcheck

Whitespace error

Column 50: trailing whitespace

Once jcheck is OK, I guess we might be good to go to resolve the issues you are facing with a parallel run

Error: Unexpected exception occurred! java.lang.NullPointerException
java.lang.NullPointerException
	at com.sun.javatest.regtest.config.TestProperties$Cache.getEntryInternal(TestProperties.java:515)
	at com.sun.javatest.regtest.config.TestProperties$Cache.getEntryInternal(TestProperties.java:515)
	at com.sun.javatest.regtest.config.TestProperties$Cache.getEntry(TestProperties.java:502)
	at com.sun.javatest.regtest.config.TestProperties.getEntry(TestProperties.java:170)
	at com.sun.javatest.regtest.config.TestProperties.getTestNGRoot(TestProperties.java:123)
	at com.sun.javatest.regtest.config.RegressionTestFinder.scanFile(RegressionTestFinder.java:143)
	at com.sun.javatest.finder.TagTestFinder.scan(TagTestFinder.java:115)
	at com.sun.javatest.TestFinder.read(TestFinder.java:433)
	at com.sun.javatest.TRT_TreeNode.processFile(TRT_TreeNode.java:1259)
	at com.sun.javatest.TRT_TreeNode.scanIfNeeded(TRT_TreeNode.java:807)
	at com.sun.javatest.TRT_TreeNode.getTreeNode(TRT_TreeNode.java:616)
	at com.sun.javatest.TestResultTable.findNode(TestResultTable.java:400)
	at com.sun.javatest.TestResultTable.lookupNode(TestResultTable.java:533)
	at com.sun.javatest.TestResultTable.lookupInitURL(TestResultTable.java:571)
	at com.sun.javatest.TestResultTable.validatePath(TestResultTable.java:1000)
	at com.sun.javatest.regtest.config.TestManager.validatePath(TestManager.java:299)
	at com.sun.javatest.regtest.config.TestManager.getTests(TestManager.java:271)
	at com.sun.javatest.regtest.tool.Tool.createParameters(Tool.java:1659)
	at com.sun.javatest.regtest.tool.Tool.run(Tool.java:1293)
	at com.sun.javatest.regtest.tool.Tool.run(Tool.java:1082)
	at com.sun.javatest.regtest.tool.Tool.main(Tool.java:155)
	at com.sun.javatest.regtest.Main.main(Main.java:46)

Some debug output showing the problem:
	scanIfNeeded getRootRelativePath= separator=/ filesToScan[i]=resultdir
	processFile file=/resultdir isAbsolute=true
	TestFinder.java read file=/resultdir isAbsolute=true
	scanFile caller file=/resultdir
	scanFile File=/resultdir
	TestProperties.java:dir=/ rootDir=/home/azul/azul/zulu11-git/test/hotspot/jtreg file2=/resultdir file2.getParentFile()=/
	TestProperties.java:dir=null rootDir=/home/azul/azul/zulu11-git/test/hotspot/jtreg file2=/resultdir file2.getParentFile()=/

This happens with jtreg using -w:resultdir . getRootRelativePath()
returns empty "" path. Other option would be to return "." but in such
case it broke some other code.

This problem does not happen during a single run. It happens only when
jtreg is being run in parallel, in my case:
	seq 1 100000|xargs -n1 -P64 ./runtest
	#! /bin/bash
	dir=result-test$$
	rm -rf $dir
	mkdir $dir
	set -o pipefail
	(JAVA_HOME=$HOME/azul/zulu11-git/build/linux-x86_64-normal-server-release/images/jdk/; $JAVA_HOME/bin/java -classpath $HOME/azul/jtreg/build/images/jtreg/lib/jtreg.jar:$HOME/azul/jtreg/build/images/jtreg/lib/javatest.jar:$HOME/azul/jtreg/build/images/jtreg/lib/asmtools.jar com.sun.javatest.regtest.Main -testjdk:$JAVA_HOME -othervm -verbose -ignore:quiet -retain:all -a -conc:1 -timeout:10 -vmoptions:-XX:+UnlockExperimentalVMOptions -w:$dir -noreport -dir:$JAVA_HOME/../../../../test/jdk/ -nativepath:$JAVA_HOME/../test/hotspot/jtreg/native ../hotspot/jtreg/vmTestbase/nsk/jdi/stress/serial/heapwalking001/TestDescription.java |& tee $dir/err) || exit 255
	rm -rf $dir
@openjdk openjdk bot added ready Pull request is ready to be integrated rfr Pull request is ready for review labels Sep 1, 2022
@jankratochvil
Copy link
Contributor Author

@dbessono I am not sure - is this patch OK or should I check whether getRootRelativePath() has returned null?
Otherwise I have fixed the whitespace, sorry for not noticing the jcheck error, it sends no mails.

@dbessono
Copy link
Collaborator

dbessono commented Sep 1, 2022

The current patch takes possible null value into account and won't generate NPE, as per https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#equals-java.lang.Object-

@dbessono dbessono self-requested a review September 1, 2022 12:11
@dbessono
Copy link
Collaborator

dbessono commented Sep 1, 2022

/integrate

@jankratochvil
Copy link
Contributor Author

It won't generate NPE but it will produce String "null/filename". Which will produce NPE later in the code like the original problem this patch tries to fix. But then we do not know what return value null from getRootRelativePath() should mean. So we do not know what to do with such return value anyway.
But I prefer it this way, thanks for the approval.

@openjdk
Copy link

openjdk bot commented Sep 1, 2022

@dbessono Only the author (@jankratochvil) is allowed to issue the integrate command.

@jankratochvil
Copy link
Contributor Author

/integrate

@openjdk openjdk bot added the sponsor Pull request requires a sponsor label Sep 1, 2022
@openjdk
Copy link

openjdk bot commented Sep 1, 2022

@jankratochvil
Your change (at version c52f73a) is now ready to be sponsored by a Committer.

@dbessono
Copy link
Collaborator

dbessono commented Sep 1, 2022

It won't generate NPE but it will produce String "null/filename". Which will produce NPE later in the code like the original problem this patch tries to fix. But then we do not know what return value null from getRootRelativePath() should mean. So we do not know what to do with such return value anyway. But I prefer it this way, thanks for the approval.

you are right, as a follow up I'd update the code to

                    processFile(path == null || path.isEmpty() // Zero length string if the node is a root

@dbessono
Copy link
Collaborator

dbessono commented Sep 1, 2022

/sponsor

@openjdk
Copy link

openjdk bot commented Sep 1, 2022

Going to push as commit 2b3e2b6.

@openjdk openjdk bot added the integrated Pull request has been integrated label Sep 1, 2022
@openjdk openjdk bot closed this Sep 1, 2022
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review sponsor Pull request requires a sponsor labels Sep 1, 2022
@openjdk
Copy link

openjdk bot commented Sep 1, 2022

@dbessono @jankratochvil Pushed as commit 2b3e2b6.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

dbessono added a commit that referenced this pull request Sep 1, 2022
@jankratochvil
Copy link
Contributor Author

I see you have already done the path == null || part so we are done, thanks!

@dbessono
Copy link
Collaborator

dbessono commented Sep 1, 2022

I see you have already done the path == null || part so we are done, thanks!

yep, could you please check that the current state of the main JTH branch allows you to unblock the testing in the configuration you are using.

@jankratochvil
Copy link
Contributor Author

I have verified:
https://github.com/jankratochvil/jtharness/tree/badnpe (=before this commit) does throw NPE
https://github.com/jankratochvil/jtharness/tree/master does not throw NPE

@dbessono
Copy link
Collaborator

dbessono commented Sep 1, 2022

I have verified: https://github.com/jankratochvil/jtharness/tree/badnpe (=before this commit) does throw NPE https://github.com/jankratochvil/jtharness/tree/master does not throw NPE

Thank you! Looks we could add a tag for b24

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
integrated Pull request has been integrated
3 participants