scala-native icon indicating copy to clipboard operation
scala-native copied to clipboard

scripted-tests java-net-server-socket appears to be broken.

Open LeeTibbert opened this issue 2 years ago • 12 comments

Another "forget-me-not" & announcement.

java-net-server-socket appears to be totally non-functional. This breakage appears to be of long duration; probably more than 5 months on SN 0.5.0 and 4 months on 0.4.n.

The test is specifically designed to exercise javalib ServerSocket#accept. Issue #3131 reports a problem with accept() which makes it totally non-functional: hard broken, both IPv4 & IPv6, that is busted.

The broken accept() in the September, 2022 PR passed java-net-server-socket so it was submitted as a PR which was then merged into SN 0.5.0 and eventually backported to SN 0.4.n series. Given the nature of the problem reported in #3131 and the fix required, it is almost absolutely certain that java-net-server-socket is broken.

The java-net-server-socket code can be described, at best, as "challenging". It makes sense to wait until the multithread code is merged and exercised before attempting a re-write.

From a first examination, it appears to me that accept() is failing in a Future and that failure is not getting propagated back to a level of java-net-server-socket which should be reporting it. Or, the error output and any failure status is going into a black hole.

LeeTibbert avatar Feb 05 '23 16:02 LeeTibbert

Oh-oh bad news. I hope this is fixable in a reasonable time. I use this as example (i.e. multi-client time server) in a small actor framework i am writing. It would be really nice to release full cross-platform (JVM, JS, Native). Thanks a lot for all your good work so far, i stay tuned! 👀

devlaam avatar Feb 05 '23 16:02 devlaam

@devlaam if you are looking for (non-blocking) sockets, may I point you towards epollcat, which Lee and I have worked on together? It implements JDK AsynchronousSocketChannel and related APIs.

https://github.com/armanbilge/epollcat

If it's helpful to your projects, note that most of the Typelevel stack runs on all three platforms: HTTP/1 and HTTP/2 server+client, Postgres client, Redis client, on JVM, Node.js, and Native.

https://typelevel.org/blog/2022/09/19/typelevel-native.html

armanbilge avatar Feb 05 '23 16:02 armanbilge

@devlaam I submitted an 0.5.0 PR with the fix this morning.

I am trying to get a clean SN 0.4.x baseline build to ensure that the code in the 0.5.0 PR backports cleanly.

I/we are/am glad that you are including Scala Native in your examples.

As a quicky, you could try building with SN 0.4.7. That was released before the broken code entered the 0.4.x stream. I am told that there is a concept in German of "Buttered Bread always falls butter side down". Here that translate to "there is probably some fix in 0.4.8 or above which you need.". Arrgh!

LeeTibbert avatar Feb 05 '23 17:02 LeeTibbert

Being exceedingly bothered about how this embarrassment escaped into the wild, I tracked down and examined the existing SN test that was supposed to exercise accept() and report flaws. That test is scripted-tests java-net-server-socket. I've created issue #3139 so that it does not get forgotten.

I also spent time remembering that @armanbilge 's typelevel code exercised client/server quite well. To date, that uses SN 0.4.x. I wondered why it passed and the SN 0.5.0 javalib flipped onto its back dead the first time it was used. Then I remembered that Arman tends to use posix sockets and avoid the java overhead.

I like to do 'defect analysis', not in the sense of finding 'fault' in the bad, recrimination, sense, but in the sense of "How did this happen so that we do not get to enjoy it again?".

LeeTibbert avatar Feb 05 '23 18:02 LeeTibbert

As a quicky, you could try building with SN 0.4.7. That was released before the broken code entered the 0.4.x stream. I am told that there is a concept in German of "Buttered Bread always falls butter side down". Here that translate to "there is probably some fix in 0.4.8 or above which you need.". Arrgh!'

Well luckily i am living in Austria, although we do speak German over here, this saying does not apply. However, i tried a couple of versions <=0.4.7 and they all give the same problem. So, it could be that my sbt is not picking up the changed version somehow. Is there a way to ask at runtime what version for building was used?

devlaam avatar Feb 06 '23 11:02 devlaam

https://github.com/armanbilge/epollcat https://typelevel.org/blog/2022/09/19/typelevel-native.html

These are interesting projects indeed. Thanks for bringing them to my attention.

devlaam avatar Feb 06 '23 11:02 devlaam

A note-to-self so I can keep track of the discussion. There are two defects in motion here. This Issue tracks the failing test, so I do not forget it. Issue #3131 tracks the underlying defect: failing javalib accept().

Issue #3131 was addressed for SN 0.5.x by merged PR #3140
The fix for SN 0.4.x stream is PR #PR #3443, which is now in CI.

There is no fix or schedule for the broken "java-net-server-socket" test.
That will be "bigger than a breadbox", to continue the bread theme.

@devlaam Motivated by your questions & experience, I went diving into the history of the file affected by Issue #3131, and the underlying defect. Looks like the underlying accept() defect was introduced 3.5+ years ago. So, none of the 4.n series (and probably none of the 3.n series) will give the "magic fix" I had been hoping for. Sorry for any time you spent on my misdirection.

Re: you question about telling which Scala Native version is actually being used by Sbt.

sbt> eval nativeVersion
[info] ans: String = 0.4.10

I ask myself that question several times a day. I am constantly switching between SN 0.5.x and 0.4.x. @armanbilge positively influences me to not forget 0.4.x, as it is in active use and 0.5.x is a dream, making massive progress towards being solid.

I have a private local.sbt which has some code to allow me to do """ sbt> show scalaNativeVersion [info] 0.4.10

// Similar/parallel to existing sbt> show javaVersion [info] 19 """

LeeTibbert avatar Feb 06 '23 17:02 LeeTibbert

Re: you question about telling which Scala Native version is actually being used by Sbt.

Unfortunately I think it's a bit more complicated for users. For example, you may have sbt-scala-native 0.4.7 in your build.

However, you may depend on a library that was published with sbt-scala-native 0.4.10. Therefore, that library has a dependency on 0.4.10 of Nativelib, Javalib, etc. So these newer versions will evict the 0.4.7 versions.

In effect, you will be using the 0.4.7 compiler toolchain with the 0.4.10 version of the Javalib library.

In summary: just because you rollback the sbt-scala-native version, doesn't mean you are using old versions of the Javalib library. This can only be determined by analyzing your entire dependency tree.

armanbilge avatar Feb 06 '23 17:02 armanbilge

Arman, thank you for that info! Guess I am too used to living in my own province.

I am constantly amazed by the cost of bugs and the difficulty of stamping them out once introduced.

I think there is an sbt plugin which will show the entire dependency tree, but I have never used it.

LeeTibbert avatar Feb 06 '23 17:02 LeeTibbert

You can use the evicted task in sbt to find out what's actually going on. Here's a little demo.

project/plugins.sbt

addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.8")

build.sbt

enablePlugins(ScalaNativePlugin)
libraryDependencies += "org.typelevel" %%% "cats-effect" % "3.4.6"
sbt:sandbox> eval nativeVersion
[info] ans: String = 0.4.8

sbt:sandbox> evicted
[info] Here are other dependency conflicts that were resolved:
[info]  * org.scala-native:nativelib_native0.4_2.12:0.4.9 is selected over 0.4.3
[info]      +- org.scala-native:posixlib_native0.4_2.12:0.4.9     (depends on 0.4.9)
[info]      +- org.scala-native:windowslib_native0.4_2.12:0.4.9   (depends on 0.4.9)
[info]      +- org.scala-native:auxlib_native0.4_2.12:0.4.9       (depends on 0.4.9)
[info]      +- org.scala-native:clib_native0.4_2.12:0.4.9         (depends on 0.4.9)
[info]      +- io.github.cquiroz:cldr-api_native0.4_2.12:3.1.0    (depends on 0.4.3)
[info]  * org.portable-scala:portable-scala-reflect_native0.4_2.12:1.1.2 is selected over 1.1.1
[info]      +- io.github.cquiroz:scala-java-time_native0.4_2.12:2.4.0 (depends on 1.1.2)
[info]      +- io.github.cquiroz:cldr-api_native0.4_2.12:3.1.0    (depends on 1.1.1)
[info]  * org.scala-native:auxlib_native0.4_2.12:0.4.9 is selected over 0.4.3
[info]      +- org.scala-native:scalalib_native0.4_2.12:0.4.8     (depends on 0.4.9)
[info]      +- io.github.cquiroz:cldr-api_native0.4_2.12:3.1.0    (depends on 0.4.3)
[info]  * org.scala-native:scalalib_native0.4_2.12:0.4.9 is selected over {0.4.8, 0.4.3, 0.4.4, 0.4.4, 0.4.4, 0.4.7, 0.4.7}
[info]      +- default:sandbox_native0.4_2.12:0.1.0-SNAPSHOT      (depends on 0.4.9)
[info]      +- org.typelevel:cats-effect_native0.4_2.12:3.4.6     (depends on 0.4.9)
[info]      +- org.typelevel:cats-effect-std_native0.4_2.12:3.4.6 (depends on 0.4.9)
[info]      +- org.typelevel:cats-effect-kernel_native0.4_2.12:3.4.6 (depends on 0.4.9)
[info]      +- org.typelevel:cats-kernel_native0.4_2.12:2.9.0     (depends on 0.4.7)
[info]      +- org.typelevel:cats-core_native0.4_2.12:2.9.0       (depends on 0.4.7)
[info]      +- org.portable-scala:portable-scala-reflect_native0.4_2.12:1.1.2 (depends on 0.4.4)
[info]      +- io.github.cquiroz:scala-java-time_native0.4_2.12:2.4.0 (depends on 0.4.4)
[info]      +- io.github.cquiroz:scala-java-locales_native0.4_2.12:1.4.0 (depends on 0.4.4)
[info]      +- io.github.cquiroz:cldr-api_native0.4_2.12:3.1.0    (depends on 0.4.3)
[info]      +- org.scala-native:scalalib_native0.4_2.12:0.4.8     (depends on 0.4.8)
[info]  * org.scala-native:javalib_native0.4_2.12:0.4.9 is selected over 0.4.3
[info]      +- org.scala-native:scalalib_native0.4_2.12:0.4.8     (depends on 0.4.9)
[info]      +- io.github.cquiroz:cldr-api_native0.4_2.12:3.1.0    (depends on 0.4.3)
[success] Total time: 0 s, completed Feb 6, 2023, 5:40:30 PM

armanbilge avatar Feb 06 '23 17:02 armanbilge

Wonderful! With (indeed in project/plugins.sbt)

addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.6")

after reload, clean, compile and run, we have

sbt:native1> eval nativeVersion
[info] ans: String = 0.4.9

and

sbt:native1> evicted
[warn] Scala version was updated by one of library dependencies:
[warn] 	* org.scala-lang:scala-library:2.13.10 is selected over {2.13.8, 2.13.8}
[warn] 	    +- org.scala-native:scalalib_native0.4_2.13:0.4.9     (depends on 2.13.10)
[warn] 	    +- org.scala-lang:scala3-library_3:3.2.0              (depends on 2.13.8)
[warn] To force scalaVersion, add the following:
[warn] 	scalaModuleInfo ~= (_.map(_.withOverrideScalaVersion(true)))
[info] Here are other dependency conflicts that were resolved:
[info] 	* org.scala-lang:scala3-library_3:3.2.0 is selected over {3.1.3, 3.1.3, 3.1.3, 3.1.3, 3.1.3, 3.1.3, 3.1.3}
[info] 	    +- default:native1_native0.4_3:0.1.0-SNAPSHOT         (depends on 3.2.0)
[info] 	    +- org.scala-native:windowslib_native0.4_3:0.4.9      (depends on 3.1.3)
[info] 	    +- org.scala-native:scala3lib_native0.4_3:0.4.9       (depends on 3.1.3)
[info] 	    +- org.scala-native:posixlib_native0.4_3:0.4.9        (depends on 3.1.3)
[info] 	    +- org.scala-native:nativelib_native0.4_3:0.4.9       (depends on 3.1.3)
[info] 	    +- org.scala-native:javalib_native0.4_3:0.4.9         (depends on 3.1.3)
[info] 	    +- org.scala-native:clib_native0.4_3:0.4.9            (depends on 3.1.3)
[info] 	    +- org.scala-native:auxlib_native0.4_3:0.4.9          (depends on 3.1.3)
[success] Total time: 0 s, completed 6 Feb 2023, 21:31:42

version 0.4.6 not even present (although i can see they libs are fetched)! Debugging gets kind of hard this way🤪

BTW, if i move to 0.4.10 this works as advertised:

addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.10")

and

sbt:native1> eval nativeVersion
[info] ans: String = 0.4.10
sbt:native1> evicted
[info] Here are other dependency conflicts that were resolved:
[info] 	* org.scala-lang:scala3-library_3:3.2.1 is selected over {3.1.3, 3.1.3, 3.1.3, 3.1.3, 3.1.3, 3.1.3, 3.1.3}
[info] 	    +- default:native1_native0.4_3:0.1.0-SNAPSHOT         (depends on 3.2.1)
[info] 	    +- org.scala-native:windowslib_native0.4_3:0.4.10     (depends on 3.1.3)
[info] 	    +- org.scala-native:scala3lib_native0.4_3:0.4.10      (depends on 3.1.3)
[info] 	    +- org.scala-native:posixlib_native0.4_3:0.4.10       (depends on 3.1.3)
[info] 	    +- org.scala-native:nativelib_native0.4_3:0.4.10      (depends on 3.1.3)
[info] 	    +- org.scala-native:javalib_native0.4_3:0.4.10        (depends on 3.1.3)
[info] 	    +- org.scala-native:clib_native0.4_3:0.4.10           (depends on 3.1.3)
[info] 	    +- org.scala-native:auxlib_native0.4_3:0.4.10         (depends on 3.1.3)
[success] Total time: 0 s, completed 6 Feb 2023, 21:39:21

Somehow i do not get it below version 0.4.9 (i adjusted to scala versions likewise).

But, to stay on topic, it does not matter anyway, so let's not waste time on this. I certainly hope we get some 0.4.11 with the socket fixed in the near future.

devlaam avatar Feb 06 '23 20:02 devlaam

And, guilt by association, scripted-tests java-net-socket should be verified as actually testing something and reporting failures, if existing.

LeeTibbert avatar Feb 07 '23 17:02 LeeTibbert