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 passing jvm options #14073

Merged
merged 3 commits into from
Dec 13, 2021
Merged

Conversation

BarkingBad
Copy link
Contributor

No description provided.

@BarkingBad BarkingBad linked an issue Dec 8, 2021 that may be closed by this pull request
@BarkingBad
Copy link
Contributor Author

@philwalk I wonder whether we correctly interpret the -J options. Actually, they have to be preprocessed earlier because we cannot inject them into JVM. The question is, whether we should check them at all in MainGenericRunner then (now we do so). I am also thinking about -D option. I feel like making "syntactic sugar" for passing -D options could be viable, yet the proper way to inject environmental variables should be passing -J-D... because they are a subset of JVM options. Is there any spec on that? WDYT?

@BarkingBad
Copy link
Contributor Author

Also passing env variable to scala3 via coursier is working, because coursier runs the JVM with given java setting, the problem is with our bash scala runner only

@smarter
Copy link
Member

smarter commented Dec 8, 2021

We should support -D and not just -J-D since the scala 2 shell scripts support -D

dist/bin/scala Outdated Show resolved Hide resolved
@BarkingBad BarkingBad marked this pull request as ready for review December 9, 2021 13:13
@BarkingBad
Copy link
Contributor Author

BarkingBad commented Dec 9, 2021

@smarter, do you think that we could backport this?

@smarter
Copy link
Member

smarter commented Dec 9, 2021

Don't think it's critical enough.

@BarkingBad
Copy link
Contributor Author

These guys have problem because of the issue

Thanks for the workaround michelou. REPL was an example. We have the same problem running a scala executable (.jar). This bug forbids us to deploy the scala suite (ias) in production.

#14005 (comment)

@smarter
Copy link
Member

smarter commented Dec 9, 2021

I'm not opposed to a backport but you'll have to ask the release manager for this release (@Kordyjan ?) to see if it can be done in time.

@philwalk
Copy link
Contributor

philwalk commented Dec 9, 2021

The first test failure is a result of the hashbang line of unglobClasspath.sc, which expects scala to treat -classpath and 'dist/target/pack/lib/*' as two separate arguments, rather than a single arg with embedded spaces. This was handled in scala3-3.0.2 within dist/bin/scala lines 78-83, as part of the fix for #10761.
I'll see if I can figure out where best to address this.

Output (click arrow to expand)

2021-12-09T15:12:25.7872572Z ===> unglobClasspathVerifyTest for script [out/bootstrap/scala3-compiler-bootstrapped/scala-3.1.2-RC1-bin-SNAPSHOT-nonbootstrapped/test-classes/scripting/unglobClasspath.sc]
2021-12-09T15:12:25.7876437Z bash is [/usr/bin/bash]
2021-12-09T15:12:25.7882719Z [/usr/bin/bash]
2021-12-09T15:12:25.7884079Z [-c]
2021-12-09T15:12:25.7887428Z [SCALA_OPTS= out/bootstrap/scala3-compiler-bootstrapped/scala-3.1.2-RC1-bin-SNAPSHOT-nonbootstrapped/test-classes/scripting/unglobClasspath.sc]
2021-12-09T15:12:26.7941440Z bad option '-classpath dist/target/pack/lib/*' was ignored
2021-12-09T15:12:27.5518229Z exception occurred while compiling , unglobClasspath.sc
2021-12-09T15:12:27.5522489Z Exception in thread "main" java.io.IOException: Is a directory
2021-12-09T15:12:27.5527509Z 	at java.base/sun.nio.ch.FileDispatcherImpl.read0(Native Method)
2021-12-09T15:12:27.5532084Z 	at java.base/sun.nio.ch.FileDispatcherImpl.read(FileDispatcherImpl.java:48)
2021-12-09T15:12:27.5535828Z 	at java.base/sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:276)
2021-12-09T15:12:27.5539025Z 	at java.base/sun.nio.ch.IOUtil.read(IOUtil.java:245)
2021-12-09T15:12:27.5542187Z 	at java.base/sun.nio.ch.FileChannelImpl.read(FileChannelImpl.java:229)
2021-12-09T15:12:27.5546078Z 	at java.base/sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:65)
2021-12-09T15:12:27.5548863Z 	at java.base/sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:107)
2021-12-09T15:12:27.5551159Z 	at java.base/sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:101)
2021-12-09T15:12:27.5553412Z 	at dotty.tools.io.AbstractFile.toByteArray(AbstractFile.scala:176)
2021-12-09T15:12:27.5555467Z 	at dotty.tools.dotc.util.SourceFile$.apply(SourceFile.scala:277)
2021-12-09T15:12:27.5557449Z 	at dotty.tools.dotc.core.Contexts$Context.getSource$$anonfun$1(Contexts.scala:276)
2021-12-09T15:12:27.5560476Z 	at dotty.tools.dotc.util.GenericHashMap.getOrElseUpdate(GenericHashMap.scala:133)
2021-12-09T15:12:27.5563106Z 	at dotty.tools.dotc.core.Contexts$Context.getSource(Contexts.scala:276)
2021-12-09T15:12:27.5564661Z 	at dotty.tools.dotc.Run.$anonfun$1(Run.scala:205)
2021-12-09T15:12:27.5566148Z 	at scala.collection.immutable.List.map(List.scala:246)
2021-12-09T15:12:27.5567775Z 	at dotty.tools.dotc.Run.compile(Run.scala:205)
2021-12-09T15:12:27.5569296Z 	at dotty.tools.dotc.Driver.doCompile(Driver.scala:39)
2021-12-09T15:12:27.5571774Z 	at dotty.tools.scripting.ScriptingDriver.compileAndRun(ScriptingDriver.scala:28)
2021-12-09T15:12:27.5574190Z 	at dotty.tools.scripting.Main$.main(Main.scala:43)
2021-12-09T15:12:27.5575976Z 	at dotty.tools.MainGenericRunner$.run$1(MainGenericRunner.scala:230)
2021-12-09T15:12:27.5577992Z 	at dotty.tools.MainGenericRunner$.main(MainGenericRunner.scala:239)
2021-12-09T15:12:27.5580265Z 	at dotty.tools.MainGenericRunner.main(MainGenericRunner.scala)

@Kordyjan
Copy link
Contributor

Kordyjan commented Dec 9, 2021

As we are still waiting for #13777, I think we can give it a try. I think if we manage to merge this PR tomorrow and have backporting PR merged no later than Monday noon we can squeeze this fix into 3.1.1-RC2.

@philwalk
Copy link
Contributor

philwalk commented Dec 9, 2021

Two of the test failures have the same cause (regression of the fix for #10761).
Inserting the following case into dist/bin/scala provided the original fix:

    -cp*|-classpath*) # partial fix for #10761
      # hashbang can combine args, e.g. "-classpath 'lib/*'"
      CLASS_PATH="${1#* *}${PSEP}"
      let class_path_count+=1
      shift
      ;;

@BarkingBad
Copy link
Contributor Author

Well, yes, but actually no.
The problem is we had these tests failing for a long long time (see https://github.com/lampepfl/dotty/runs/4470356079?check_suite_focus=true#step:9:764) - the SCALA_HOME is empty and every test was failing silently

I enabled them by adding dist/pack. Then it appeared some of them are failing. The problem is that the shebang on linux cannot take parameters. I fixed it using this trick: https://unix.stackexchange.com/a/477651

The third problem was with handling our SCALA_OPTS property. For empty value we were passing empty string, which was breaking the compilation.

Now it should work as expected

@BarkingBad
Copy link
Contributor Author

I also had to remove the ReplTests which cannot work - we are using mock driver in the same JVM context, thus we cannot just pass the -D option, because it won't be set up anywhere

@philwalk
Copy link
Contributor

philwalk commented Dec 9, 2021

Now it should work as expected

The -S option of /usr/bin/env doesn't seem to be supported in two of my test environments. Here's what I see in Ubuntu bash, for example:

/usr/bin/env: invalid option -- 'S'
Try '/usr/bin/env --help' for more information.

@BarkingBad
Copy link
Contributor Author

It is working from coreutils 8.30 according to stack answer. For me, it was working locally as expected. Nonetheless, it's not our problem, but Linux, so if one's environment doesn't support multiple arguments in a shebang using this trick, he cannot benefit from it either way.

@BarkingBad
Copy link
Contributor Author

@philwalk now since I "enabled" scripting tests do you mind adding some assertions when the scripts fail? Many of them have the if checking if the process was successful, but there is no else branch to throw some kind of assertion error to raise the problem, for example here we just skip the validTest == false, or is it made intentionally?

@philwalk
Copy link
Contributor

philwalk commented Dec 9, 2021

It is working from coreutils 8.30 according to stack answer. For me, it was working locally as expected. Nonetheless, it's not our problem, but Linux, so if one's environment doesn't support multiple arguments in a shebang using this trick, he cannot benefit from it either way.

I'm running Ubuntu 18.04, which specifies coreutils 8.28.

@philwalk now since I "enabled" scripting tests do you mind adding some assertions when the scripts fail? Many of them have the if checking if the process was successful, but there is no else branch to throw some kind of assertion error to raise the problem, for example here we just skip the validTest == false, or is it made intentionally?

It was intentional, based on feedback in this discussion: #12962 . The assumption is that if we're unable to run the test, that's different than if the test is run but fails. If either java or scala are not in the PATH, should we fail the test? Perhaps so. The following environment variables may need to be properly initialized for environments that fail BashScriptsTests:

TEST_BASH=<path-to-bash>
TEST_CWD=<test-working-directory>
JAVA_HOME=<path-to-jvm>
SCALA_HOME='/mnt/c/dotty/dist/target/pack'
PATH="$JAVA_HOME/bin:$SCALA_HOME/bin:$PATH"

FWIW, the 5 failing tests are running in an environment with JAVA_HOME undefined, and with the first java in the PATH is at /usr/lib/jvm/java-16-openjdk-amd64/bin, whereas the error message implies that the tests are running under java 8 (class file version 52)

@philwalk
Copy link
Contributor

philwalk commented Dec 9, 2021

@philwalk now since I "enabled" scripting tests do you mind adding some assertions when the scripts fail?
I will do so, if nobody objects.

@philwalk
Copy link
Contributor

philwalk commented Dec 9, 2021

the proper way to inject environmental variables should be passing -J-D... because they are a subset of JVM options. Is there any spec on that? WDYT?

I think we should emulate scala2 behavior, any other approach will add to the migration burden for users.

@philwalk
Copy link
Contributor

philwalk commented Dec 9, 2021

@BarkingBad
After reviewing BashScriptsTests.scala, it appears that a test is not considered valid unless bash can be executed.

Unless every test environment provides bash, and has adequate permissions to execute it, the current behavior seems to be necessary. Perhaps I didn't understand your suggestion.

@philwalk
Copy link
Contributor

philwalk commented Dec 9, 2021

The problem is we had these tests failing for a long long time

Do you have a link to a discussion of this issue? The link you provided currently shows passing tests.

@philwalk
Copy link
Contributor

I'm almost ready to push an updated BashScriptsTests.scala, hopefully it will fix the problem with these failed tests.

@BarkingBad
Copy link
Contributor Author

The problem is we had these tests failing for a long long time

Do you have a link to a discussion of this issue? The link you provided currently shows passing tests.

The test is passing, but it prints stderr with non zero return codes

@BarkingBad
Copy link
Contributor Author

I'm away from home for the weekend, but as I looked yesterday on logs there was some stderr pointing to different java versions IIRC, yet I had no time to fix it (it's CI subject problem, not the scala logic)

@philwalk
Copy link
Contributor

philwalk commented Dec 10, 2021

@BarkingBad
I have a fix that I'm testing now (see the diff section below).
It makes a change to the script environment PATH, and hopefully will fix these test failures.

(it's CI subject problem, not the scala logic)

It seems that it might be scala logic, because the CI environment is seen by BashScriptsTests, but we're launching a bash command line with a different process environment. I'm doing some experiments to become more familiar with the problem.

Assuming it solves this problem, what's the best way to provide this update? I can do a PR.

Here's the git diff:

click to expand:

diff --git a/compiler/test/dotty/tools/scripting/BashScriptsTests.scala b/compiler/test/dotty/tools/scripting/BashScriptsTests.scala
index 1cdb700d5a..470f53acda 100644
--- a/compiler/test/dotty/tools/scripting/BashScriptsTests.scala
+++ b/compiler/test/dotty/tools/scripting/BashScriptsTests.scala
@@ -167,6 +167,7 @@ class BashScriptsTests:
     def exists: Boolean = s.toPath.toFile.exists
     def name: String = s.toFile.getName
     def dropExtension: String = s.reverse.dropWhile(_ != '.').drop(1).reverse
+    def parent(up: Int): String = s.norm.split("/").reverse.drop(up).reverse.mkString("/")
   }
 
   extension(p: Path) {
@@ -201,22 +202,21 @@ class BashScriptsTests:
     if scalacPath.isFile then scalacPath.replaceAll("/bin/scalac", "")
     else envOrElse("SCALA_HOME", "").norm
 
-  lazy val javaHome = envOrElse("JAVA_HOME", "").norm
+  lazy val javaHome = whichJava.parent(2)
 
   lazy val testEnvPairs = List(
+    ("whichJava", whichJava),
     ("JAVA_HOME", javaHome),
     ("SCALA_HOME", scalaHome),
     ("PATH", adjustedPath),
   ).filter { case (name, valu) => valu.nonEmpty }
 
-  lazy val whichBash: String =
-    var whichBash = ""
-    if osname.startsWith("windows") then
-      whichBash = which("bash.exe")
-    else
-      whichBash = which("bash")
+  lazy val whichBash: String = whichExe("bash")
+  lazy val whichJava: String = whichExe("java")
 
-    whichBash
+  def whichExe(basename: String): String = 
+    val exeName = if (osname.toLowerCase.startsWith("windows")) s"$basename.exe" else basename
+    which(exeName)
 
   def bashCommand(cmdstr: String, additionalEnvPairs: List[(String, String)] = Nil): (Boolean, Int, Seq[String], Seq[String]) = {
     var (stdout, stderr) = (List.empty[String], List.empty[String])

@BarkingBad
Copy link
Contributor Author

@philwalk can you push directly on top of my branch? I think it is possible for maintainers. If not, maybe you could do some branch with fix and I'll cherry-pick your commit, would that be OK?

This sets `javaHome` at the head of the PATH for `bashCommands`.
@philwalk
Copy link
Contributor

I was able to update BashScriptsTests on this branch. Hopefully this resolves the tests.

Copy link
Contributor

@philwalk philwalk left a comment

Choose a reason for hiding this comment

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

LGTM

@BarkingBad BarkingBad merged commit dcb123d into scala:master Dec 13, 2021
@BarkingBad
Copy link
Contributor Author

@Kordyjan should we backport these changes?

@BarkingBad
Copy link
Contributor Author

@philwalk apparently this PR broke CI on master: the logs are:

Logs

 cwd: /__w/dotty/dotty
classpath: /__w/dotty/dotty:/__w/dotty/dotty/dist/target/pack/lib/scala-library-2.13.6.jar:/__w/dotty/dotty/dist/target/pack/lib/scala3-library_3-3.1.2-RC1-bin-SNAPSHOT.jar:/__w/dotty/dotty/dist/target/pack/lib/scala-asm-9.1.0-scala-1.jar:/__w/dotty/dotty/dist/target/pack/lib/compiler-interface-1.3.5.jar:/__w/dotty/dotty/dist/target/pack/lib/scala3-interfaces-3.1.2-RC1-bin-SNAPSHOT.jar:/__w/dotty/dotty/dist/target/pack/lib/scala3-compiler_3-3.1.2-RC1-bin-SNAPSHOT.jar:/__w/dotty/dotty/dist/target/pack/lib/tasty-core_3-3.1.2-RC1-bin-SNAPSHOT.jar:/__w/dotty/dotty/dist/target/pack/lib/scala3-staging_3-3.1.2-RC1-bin-SNAPSHOT.jar:/__w/dotty/dotty/dist/target/pack/lib/scala3-tasty-inspector_3-3.1.2-RC1-bin-SNAPSHOT.jar:/__w/dotty/dotty/dist/target/pack/lib/jline-reader-3.19.0.jar:/__w/dotty/dotty/dist/target/pack/lib/jline-terminal-3.19.0.jar:/__w/dotty/dotty/dist/target/pack/lib/jline-terminal-jna-3.19.0.jar:/__w/dotty/dotty/dist/target/pack/lib/jna-5.3.1.jar:dist/target/pack/lib/protobuf-java-3.7.0.jar:dist/target/pack/lib/flexmark-ext-emoji-0.42.12.jar:dist/target/pack/lib/compiler-interface-1.3.5.jar:dist/target/pack/lib/flexmark-ext-anchorlink-0.42.12.jar:dist/target/pack/lib/scala3-staging_3-3.1.2-RC1-bin-SNAPSHOT.jar:dist/target/pack/lib/jna-5.3.1.jar:dist/target/pack/lib/liqp-0.6.8.jar:dist/target/pack/lib/snakeyaml-1.23.jar:dist/target/pack/lib/ST4-4.0.7.jar:dist/target/pack/lib/flexmark-ext-autolink-0.42.12.jar:dist/target/pack/lib/dist_3-3.1.2-RC1-bin-SNAPSHOT.jar:dist/target/pack/lib/flexmark-0.42.12.jar:dist/target/pack/lib/jsoup-1.13.1.jar:dist/target/pack/lib/antlr-3.5.1.jar:dist/target/pack/lib/util-interface-1.3.0.jar:dist/target/pack/lib/flexmark-formatter-0.42.12.jar:dist/target/pack/lib/flexmark-jira-converter-0.42.12.jar:dist/target/pack/lib/scala3-library_3-3.1.2-RC1-bin-SNAPSHOT.jar:dist/target/pack/lib/antlr-runtime-3.5.1.jar:dist/target/pack/lib/flexmark-ext-ins-0.42.12.jar:dist/target/pack/lib/flexmark-ext-gfm-tables-0.42.12.jar:dist/target/pack/lib/autolink-0.6.0.jar:dist/target/pack/lib/jackson-dataformat-yaml-2.9.8.jar:dist/target/pack/lib/scala3-tasty-inspector_3-3.1.2-RC1-bin-SNAPSHOT.jar:dist/target/pack/lib/flexmark-html-parser-0.42.12.jar:dist/target/pack/lib/jline-reader-3.19.0.jar:dist/target/pack/lib/scala3-interfaces-3.1.2-RC1-bin-SNAPSHOT.jar:dist/target/pack/lib/jline-terminal-3.19.0.jar:dist/target/pack/lib/flexmark-util-0.42.12.jar:dist/target/pack/lib/flexmark-ext-gfm-strikethrough-0.42.12.jar:dist/target/pack/lib/jackson-databind-2.2.3.jar:dist/target/pack/lib/tasty-core_3-3.1.2-RC1-bin-SNAPSHOT.jar:dist/target/pack/lib/jackson-core-2.9.8.jar:dist/target/pack/lib/flexmark-ext-wikilink-0.42.12.jar:dist/target/pack/lib/flexmark-ext-superscript-0.42.12.jar:dist/target/pack/lib/scaladoc_3-3.1.2-RC1-bin-SNAPSHOT.jar:dist/target/pack/lib/flexmark-ext-gfm-tasklist-0.42.12.jar:dist/target/pack/lib/scala-asm-9.1.0-scala-1.jar:dist/target/pack/lib/scala-library-2.13.6.jar:dist/target/pack/lib/flexmark-ext-tables-0.42.12.jar:dist/target/pack/lib/flexmark-ext-yaml-front-matter-0.42.12.jar:dist/target/pack/lib/scala3-compiler_3-3.1.2-RC1-bin-SNAPSHOT.jar:dist/target/pack/lib/jline-terminal-jna-3.19.0.jar:dist/target/pack/lib/jackson-annotations-2.2.3.jar
output  []
expected[/__w/dotty/dotty]
osname[linux]
Error:  Test dotty.tools.scripting.BashScriptsTests.verifyScalaOpts failed: java.lang.AssertionError: assertion failed: script /__w/dotty/dotty/compiler/target/scala-3.1.1-RC1/test-classes/scripting/classpathReport.sc did not report valid java.class.path first entry, took 55.464 sec

This is strange, becuase there is cwd in logs. Do you have any idea why it failed on non-bootstrapped tests?

@BarkingBad
Copy link
Contributor Author

Also, test_windows_full failed because of missing artifacts (it didn't come up in PR because there is only fast check), this PR should fix it, and check if test_windows_full is passing #14106

@philwalk
Copy link
Contributor

philwalk commented Dec 14, 2021

Do you have any idea why it failed on non-bootstrapped tests?

I'm investigating now ...

The test assumes that the current working directory is the first entry on the classpath, which appears to be the case.
However, there's a possibility that a leading space or other artifact is interfering with the assumptions. It would help if we dump stdout and stderr in cases where a failure occurs.

I notice that the first line of output has a leading space ahead of cwd: , which is unexpected, although it doesn't look like that could explain it.

I have refactored all of the compiler/test/dotty/tools/scripting sources to factor out common code among the tests, and the new version dumps stdout and stderr on failures, plus other information. I'll created a new PR #14108, and it provides addition output to the logfile that should be helpful in diagnosing this.

Also, I changed the code that stripped the "cwd: " off of the first line of script output to get the "output[]" value, and now, rather than strip the "cwd: " prefix, I test whether cwdline.endsWith(expected). That way, we can see the full line in the test logs, if something goes wrong.

@philwalk
Copy link
Contributor

The following error is caused by the /usr/bin/env -S change, which cygwin is incompatible with:

2021-12-14T03:12:25.6948093Z ===> verify SCALA_OPTS='@argsfile' is properly handled by `dist/bin/scala`
2021-12-14T03:12:25.7438839Z stderr [Try '/usr/bin/env --help' for more information.]
2021-12-14T03:12:25.7439130Z 
2021-12-14T03:12:25.7439380Z unable to execute script, return value is 125
2021-12-14T03:12:25.7439729Z stderr [env: unknown option -- S]
2021-12-14T03:12:25.7439965Z stdout: 
2021-12-14T03:12:25.7440090Z 

Cygwin does not yet support coreutils 8.30:

$ /usr/bin/env --version
env (GNU coreutils) 8.26
Packaged by Cygwin (8.26-2)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

One fix might be to add this back to dist/bin/scala:

    -cp*|-classpath*) # partial fix for #10761
      # hashbang can combine args, e.g. "-classpath 'lib/*'"
      CLASS_PATH="${1#* *}${PSEP}"
      let class_path_count+=1
      shift
      ;;

@BarkingBad BarkingBad mentioned this pull request Dec 17, 2021
@Kordyjan Kordyjan added this to the 3.1.2 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cannot pass system properties in comand line
4 participants