<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<!--[if !mso]><style>v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style><![endif]--><style><!--
/* Font Definitions */
@font-face
{font-family:Helvetica;
panose-1:0 0 0 0 0 0 0 0 0 0;}
@font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:Aptos;
panose-1:2 11 0 4 2 2 2 2 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
font-size:10.0pt;
font-family:"Aptos",sans-serif;}
h3
{mso-style-priority:9;
mso-style-link:"Heading 3 Char";
mso-margin-top-alt:auto;
margin-right:0in;
mso-margin-bottom-alt:auto;
margin-left:0in;
font-size:13.5pt;
font-family:"Aptos",sans-serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:#467886;
text-decoration:underline;}
span.Heading3Char
{mso-style-name:"Heading 3 Char";
mso-style-priority:9;
mso-style-link:"Heading 3";
font-family:"Aptos",sans-serif;
color:#0F4761;}
span.EmailStyle230
{mso-style-type:personal-reply;
font-family:"Aptos",sans-serif;
color:windowtext;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;
mso-ligatures:none;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
/* List Definitions */
@list l0
{mso-list-id:422923455;
mso-list-type:hybrid;
mso-list-template-ids:-1097546596 -996392306 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l0:level1
{mso-level-number-format:bullet;
mso-level-text:\F0B7 ;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Symbol;
mso-fareast-font-family:Aptos;
mso-bidi-font-family:"Times New Roman";}
@list l0:level2
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:"Courier New";}
@list l0:level3
{mso-level-number-format:bullet;
mso-level-text:\F0A7 ;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Wingdings;}
@list l0:level4
{mso-level-number-format:bullet;
mso-level-text:\F0B7 ;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Symbol;}
@list l0:level5
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:"Courier New";}
@list l0:level6
{mso-level-number-format:bullet;
mso-level-text:\F0A7 ;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Wingdings;}
@list l0:level7
{mso-level-number-format:bullet;
mso-level-text:\F0B7 ;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Symbol;}
@list l0:level8
{mso-level-number-format:bullet;
mso-level-text:o;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:"Courier New";}
@list l0:level9
{mso-level-number-format:bullet;
mso-level-text:\F0A7 ;
mso-level-tab-stop:none;
mso-level-number-position:left;
text-indent:-.25in;
font-family:Wingdings;}
ol
{margin-bottom:0in;}
ul
{margin-bottom:0in;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="#467886" vlink="purple" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt">> </span><span style="font-size:12.0pt">It's hard to know if there if there is a case where concurrent reads from the same TCP/socket stream make sense ... If there is a protocol where it's possible to do
something sensible when reading subsets of bytes, and with different timeouts, or code handling SocketTimeoutException then maybe your point could be looked ...</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Yes, a conscious design involving concurrent Socket use would be a strange thing, no argument there. Also, your point about connect() makes total sense.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Going back to read(), what would be the way out of the situation for the API users? The app has detected stale data in the socket buffer and tries to clean things up. It isn’t aware the other reader is still
alive and calls JDBC abort(). The JDBC spec allows Connection sharing, the driver isn’t even obliged to check for concurrency. Sure, it is doing a questionable read(), but while taking the timeout precautions.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">In this situation NIO is the only player aware of the other reader. Which brings us to the choice: try to eliminate the reason the other player is holding the lock (which sounds like an uphill battle) or behave
transparently to the lock presence: wait for the timeout interval and return -1 like if there was no data. Besides, the lock is an internal library mechanism whose existence has only surfaced accidently.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">From the API user standpoint, the second option sounds simpler to handle. Not saying we ever will but should someone want to code around a hund read, that’d bring a lot of complexity.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">> </span><span style="font-size:12.0pt">I'd prefer not use that to justify doing something to help a workaround when it does happen.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Please note that we’d not make the situation worse than today, should somebody attempt to call read() concurrently. The logical difference would be “the call returned no data because **there is** no data”
vs “the call returned no data because somebody else is reading it and we’ve timed out” (as opposed to today’s “wait for an uncertain interval till the other party has finished their read”).<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<div>
<div>
<p class="MsoNormal"><span style="font-size:9.0pt;font-family:"Calibri",sans-serif">-- <o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><span style="font-size:9.0pt;font-family:"Calibri",sans-serif">Regards, Alexei</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<div id="mail-editor-reference-message-container">
<div>
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">From:
</span></b><span style="font-size:12.0pt;color:black">Alan Bateman <alan.bateman@oracle.com><br>
<b>Date: </b>Thursday, May 29, 2025 at 10:40<br>
<b>To: </b>Alexei Olkhovskii <alexei.olkhovskii@servicenow.com>, nio-dev@openjdk.org <nio-dev@openjdk.org><br>
<b>Subject: </b>Re: NIO Socket.read() may not respect the socket timeout<o:p></o:p></span></p>
</div>
<div>
<h3><strong><span style="font-family:Helvetica;color:black;background:yellow">[External Emai</span></strong><span style="font-family:Helvetica"><o:p></o:p></span></h3>
<p class="MsoNormal"><span style="font-size:12.0pt;font-family:Helvetica"><o:p> </o:p></span></p>
<div class="MsoNormal" align="center" style="text-align:center"><span style="font-size:12.0pt;font-family:Helvetica">
<hr size="0" width="100%" align="center">
</span></div>
</div>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:12.0pt"><o:p> </o:p></span></p>
<div>
<p class="MsoNormal"><span style="font-size:12.0pt">On 28/05/2025 20:46, Alexei Olkhovskii wrote:<o:p></o:p></span></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:11.0pt">>
</span><span style="font-size:12.0pt">This may be an issue with the reserved stack area. There was work done in JDK 9 via JEP 270 [1] but I think it needs to be looked at again.</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Perhaps <a href="https://bugs.openjdk.org/browse/JDK-8318888">
https://bugs.openjdk.org/browse/JDK-8318888</a> is also relevant.</span><o:p></o:p></p>
</div>
</blockquote>
<p class="MsoNormal"><span style="font-size:12.0pt"><br>
Yes, there are a few reports of issues when continuing after SOE.<br>
<br>
<br>
<br>
<o:p></o:p></span></p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">But regardless of the reason the other thread is holding the lock, don’t you think the socket timeout should be respected for read(), connect(), etc?</span><o:p></o:p></p>
</div>
</blockquote>
<p class="MsoNormal"><span style="font-size:12.0pt"><br>
The connect method is only allowed once. It would be strange to create an unconnected Socket and then attempt to have 2 threads invoke connect. The second attempt must fail with SocketException (it will be "Connection in progress" or "Socket closed"). You are
right that the second attempt will block, maybe beyond the connect timeout it specifies, before it throws the SocketException. I don't think this is worth spending time on as there is impossible for the second connect to succeed.<br>
<br>
It's hard to know if there if there is a case where concurrent reads from the same TCP/socket stream make sense. At one point it was possible to have a Socket to a UDP socket but that mis-feature is deprecated a long time ago. If several threads are reading
from the same stream then it requires coordination at a higher level, something that understands the protocol, meaning the lock contention will be further up the stack. If there is a protocol where it's possible to do something sensible when reading subsets
of bytes, and with different timeouts, or code handling SocketTimeoutException then maybe your point could be looked. For now, I think the issue here is the "lock corruption" and we need to understand this a bit more. I'd prefer not use that to justify doing
something to help a workaround when it does happen.<br>
<br>
-Alan<o:p></o:p></span></p>
</div>
</div>
</div>
</div>
</body>
</html>