Repository navigation
test: flaky parallel/test-net-connect-local-error on macOS & freeBSD #12950
Description
Activity
- addedmacosIssues and PRs related to the macOS platform.Issues and PRs related to the macOS platform.testIssues and PRs related to Node.js core tests and test infrastructure.Issues and PRs related to Node.js core tests and test infrastructure.netIssues and PRs related to the net subsystem.Issues and PRs related to the net subsystem.
on May 10, 2017 - changed the title
[-]test: flaky parallel/test-net-connect-local-error on macOS[/-][+]test: flaky parallel/test-net-connect-local-error on macOS & freeBSD[/+]on May 10, 2017 - addedfreebsdIssues and PRs related to the FreeBSD platform.Issues and PRs related to the FreeBSD platform.
on May 10, 2017 Can I take this one?
@sebastianplesciuc you like these ones 😉 . dibs is yours.
P.S. I've been told that the use ofcommon.PORTis fragile in macOS / freeBSD.
There's a general goal to use0as port (if possible) and then figure out which port the OS assigned.Reacted by Sebastian PlesciucRef: #12376
I think that's the case here as well.
I think there are two issues with this, one is that
server.close()might be called before the client's callback which is the error on line 15 I believe.Another issue might arise with
port + 1. We have no guarantee that this is an empty port when this runs. A way of fixing this might be creating another server with port0and assigning it's port to the client socket in it'sclosecallback. Thoughts? Is it guaranteed to be in use while the callback is running fromnet.Serverclose event?- The close is definitely in a bad place
- When
net.Server.closecall the cb the server will not answer anymore, so it's a good time to try to connect to it (to get an error)
Another option is to loopport + 1...5, if that's simpler.
Worse case we can move it to
/sequential/where it will run alone.@sebastianplesciuc You might appreciate this. I've been looking at this issue's brother #12951.
These tests are run in parallel first this one, then the other.
In the other one there's a server that's supposed to receive 6 connections, instead it received 7.
I wonder where that 7th request comes from 🤣@refack I'm not sure I get it :) You're suggesting that the connection in that test comes from this one? How does that work?
@refack OOOOH! I think I get it now. So when that test fails, this test fails because it connects from this test to the server from that test. So fixing this test would fix that one?
Reacted by Refael AckermannYep
P.S. I've been told that the use of common.PORT is fragile in macOS / freeBSD.
There's a general goal to use 0 as port (if possible) and then figure out which port the OS assigned.Using 0 to choose a random port can be fragile on BSD systems (including macOS) too, because of how
SO_REUSEADDRworks in their implementations of TCP. Recently I observedtest/parallel/test-http-extra-responsefailing on my machine trying to communicate with the server of an autocompletion plugin for Vim instead of the server created in the test itself. The problem is that when a process binds to port 0 withSO_REUSEADDR, the kernel may give it a port that another process is already listening on if one of them binds to a concrete address (like127.0.0.1) and the other — to a wildcard one. The logic that the kernel uses to route requests between them is not very clear to me./cc @nodejs/testing
P.S. I've been told that the use of common.PORT is fragile in macOS / freeBSD.
Hmmm, this sounds like there's a misunderstanding somewhere. There's nothing macOS or FreeBSD specific about the
common.PORTstuff as far as I know. And there's nothing fragile aboutcommon.PORT.The reason we don't typically want to use
common.PORTinparallelis to prevent this scenario:Test A uses port
0for something. Test B usescommon.PORTfor something. Test A starts to run first. The OS gives it an open port that just happens to be the same value ascommon.PORTwill be when Test B runs. Test B starts to run but Test A is already using the port it requests viacommon.PORTand so Test B fails.If Test B were in
sequentialrather thanparallel, then there wouldn't be a problem.The port collision scenario described above may sound unlikely, but it has been observed in CI results (or at least things that look suspiciously like it).
Also:
common.PORTandcommon.PORT + 1insequentialis safe (assuming no non-Node.js processes grab the ports) so you could just consider moving tosequentialif the logic gets too hairy otherwise. It's probably not anyone's first choice for a solution, but it probably shouldn't be the last choice either :-DAlso also, and this starts to enter rant territory so feel free to tune out right now: There seems to be a reluctance to move tests to
sequentialout of concerns for making the test suite run longer. I know I've certainly been reluctant. I believe now that these concerns are massively overblown. First, a lot of CI hosts (most?) don't run any tests inparalleland these include our absolute far-and-away slowest hosts. So moving something tosequentialwill have no impact whatsoever on the test suite duration for the slowest hosts. And on the faster hosts, we're generally talking about shaving off something on the order of a tenth of a second. And a lot of that benefit is probably lost by the introduction of somewhat more complicated code to make it safe to run in parallel. So we're making the code more complex but not actually getting any benefit out of it. Or at least, that's my theory. It would be fun to compare how long the test suite takes if everything in parallel were moved to sequential. I might do that right now.UPDATE (still in rant mode, so feel free to skip): Ran the test benchmark described above. Normal parallel test run on my computer was about 90 seconds. Running the same tests sequentially took about 250 seconds. That's pretty good, but it's worth noting that with 1333 tests, each test moved from
paralleltosequentialwill cost about 120ms. The question becomes: Is the added code complexity worth saving 120ms on a test suite that (once you add in the addon tests and tests insequentialand so on) takes about 2.5 minutes to run. For any significant complexity increase, the answer is always going to be "no".Reacted by Oleksii Orlenko and Joyee CheungThere seems to be a reluctance to move tests to sequential ... each test moved from parallel to sequential will cost about 120ms
@Trott IMHO it's not just the perf cost; it's the implicit assumption that testing in parallel is more vigorous, hence more rigorous. which is kinda true. A good mechanism could be to add a fourth flag to
parallel.status:TRY_SEQ, to flag the harness that for a particular test is it fail in parallel, decision should be relegated until the test is run alone.
[that was me being grandiloquent]- added a commit that references this issue
on May 16, 2017 - added a commit that references this issue
on May 16, 2017 - added a commit that references this issue
on May 19, 2017 - added a commit that references this issue
on Jun 22, 2017 - added a commit that references this issue
on Jul 11, 2017
masterhttps://ci.nodejs.org/job/node-test-commit-freebsd/8933/nodes=freebsd11-x64/tapResults/
https://ci.nodejs.org/job/node-test-commit-osx/9696/nodes=osx1010/tapResults/