battleblow / openjdk-jdk11u

BSD port of OpenJDK 11
GNU General Public License v2.0
9 stars 8 forks source link

Socket.setSoLinger doesn't behave as expected on BSD #64

Closed battleblow closed 5 years ago

battleblow commented 5 years ago

The following internal JDK test attempts to set the SO_LINGER value to one higher than 65535, expecting it to be truncated to that value. This does not work on *BSD (tested FreeBSD and OpenBSD).

Note that this truncation happens within the Java code, so it isn't expected that the OS itself do the truncation. However, the values acceptable to the OS are system dependent AFAIK, so this may have an impact.

The behaviour of this test on FreeBSD is that the call to getSoLinger returns a value of -1 when the value of 65546 is passed. Note that passing a value such as 10 does yield a return value of 10, so most likely values do appear to work.

battleblow commented 5 years ago

FYI, the test does pass correctly on Linux. I have not tried it on MacOS X yet though.

battleblow commented 5 years ago

Running a few tests with different values, values up to 32767 work correctly. Values over that wrap, leading me to conclude that either at the OS level or somewhere in the JDK code BSD is using a signed short (int16) to hold the value.

battleblow commented 5 years ago

Test does work correctly on MacOS X too.

battleblow commented 5 years ago

It looks to me like this is at the OS level. Relevant source reference for FreeBSD:

https://svnweb.freebsd.org/base/head/sys/sys/socketvar.h?revision=344956&view=markup#l89

I.e., a short is used to store the linger time for the socket.

battleblow commented 5 years ago

My conclusion is that the code in the JDK is making an assumption about operating system defined behaviour that doesn't hold true on BSD.

The remedy I'd advocate for here is to change the Java code to truncate to 32767 on BSD rather than 65535.

battleblow commented 5 years ago

Given that the value here is in seconds, maybe it would be reasonable to change the value to 32767 across the board rather than introducing OS dependent limits. Having a linger maximum timeout of over 9 hours certainly seems reasonable to me at least. I don't know what use case there would be for holding a socket open for up to 18 hours instead.

battleblow commented 5 years ago

I've pushed a change to the jck-testing branch that limits the value to 32767, as I think that is the most reasonable solution. I'll get some feedback before merging back though.

battleblow commented 5 years ago

Merged that change. This might cause some issues in compliance testing if a test is included which checks for the ability to set a higher linger value. However, since BSD can't support that, it wouldn't matter either way. This way produces consistent behaviour across all OSes and doesn't complicate the code with OS dependent checks.