fix SendTo with SocketAsyncEventArgs - #98134

Merged
wfurt merged 6 commits into
dotnet:mainfrom
wfurt:SocketAsyncEventArgs
Feb 27, 2024
Merged

fix SendTo with SocketAsyncEventArgs#98134
wfurt merged 6 commits into
dotnet:mainfrom
wfurt:SocketAsyncEventArgs

Conversation

@wfurt

@wfurtwfurt commented Feb 7, 2024

Copy link
Copy Markdown
Member

Fixes#97965 and #99863 -- a regression from PR #90086 (in 8.0).

With the new SocketAddress changes the task based IO worked because SendToAsync explicitly sets saea._socketAddress to null. But there is no access to it for anybody using SocketAsyncEventArgs directly.

In the past, RemoteEndPoint was only user accessible variable and _socketAddress was always managed internally. With the new API SendTo and ReceiveFrom can use SocketAddress directly and reference would be also set on SocketAsyncEventArgs. As I realized, 1) we should make no assumption about and and we should not try to use it for anything else than just the particular call and 2) SocketAsyncEventArgs can be used directly so any related logic really needs to be at the bottom and not in the layers above.

With that I made changes to set RemoteEndPoint to null to indicate that SendTo and ReceiveFrom was invoked with user provided SocketAddress. We will also detach it from SocketAsyncEventArgs in that case so it can be re-used for another operations safely.
On other cases we can keep it around and simply override _socketAddress as we see fit instead of allocating new one every time.

@wfurtwfurt added this to the 9.0.0 milestone Feb 7, 2024
@wfurt
wfurt requested a review from a teamFebruary 7, 2024 22:47
@wfurtwfurt self-assigned this Feb 7, 2024
@ghost

ghost commented Feb 7, 2024

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

this fixes regression from #90086 and fixes #97965.

With the new SocketAddress changes the task based IO worked because SendToAsync explicitly sets saea._socketAddress to null. But there is no access to it for anybody using SocketAsyncEventArgs directly.

In the past, RemoteEndPoint was only user accessible variable and _socketAddress was always managed internally. With the new API SendTo and ReceiveFrom can use SocketAddress directly and reference would be also set on SocketAsyncEventArgs. As I realized, 1) we should make no assumption about and and we should not try to use it for anything else than just the particular call and 2) SocketAsyncEventArgs can be used directly so any related logic really needs to be at the bottom and not in the layers above.

With that I made changes to set RemoteEndPoint to null to indicate that SendTo and ReceiveFrom was invoked with user provided SocketAddress. We will also detach it from SocketAsyncEventArgs in that case so it can be re-used for another operations safely.
On other cases we can keep it around and simply override _socketAddress as we see fit instead of allocating new one every time.

Author:wfurt
Assignees:wfurt
Labels:

area-System.Net.Sockets

Milestone:9.0.0

finally
{
// detach user provided SA so we do not accidentally stomp on it later.
saea._socketAddress = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's ok to null it here because it's only used synchronously as part of the send operation and not asynchronously?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

yes. We will make _socketAddress before first try. f we do not finish synchronously on Unix, it would be copied to queued *SendOperation. For Windows, the const sockaddr *lpTo is IN for WSASendTo and AFAIK it does not need to be preserved until the overlapped IO is completed.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
if (_remoteEndPoint == null)
{
// detach user provided SA as it was updated in place.
_socketAddress = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The only two operations it would be set for are ReceiveFrom and SendTo, and we already handled the SendTo case on the synchronous start path?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

yes. For SendTo we clear it when operation starts, for ReceiveFrom we do it when the operation is finished.

@wfurt
wfurt merged commit f9637f1 into dotnet:mainFeb 27, 2024
@wfurt
wfurt deleted the SocketAsyncEventArgs branch February 27, 2024 16:50
@wfurt

Copy link
Copy Markdown
MemberAuthor

/backport to release/8.0-staging

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8268148999

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 26, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reusing the same SocketAsyncEventArgs for different udp remote endpoints does not work anymore

2 participants

@wfurt@stephentoub
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix SendTo with SocketAsyncEventArgs - #98134

Merged
wfurt merged 6 commits into
dotnet:mainfrom
wfurt:SocketAsyncEventArgs
Feb 27, 2024
Merged

fix SendTo with SocketAsyncEventArgs#98134
wfurt merged 6 commits into
dotnet:mainfrom
wfurt:SocketAsyncEventArgs

Conversation

@wfurt

@wfurtwfurt commented Feb 7, 2024

Copy link
Copy Markdown
Member

Fixes#97965 and #99863 -- a regression from PR #90086 (in 8.0).

With the new SocketAddress changes the task based IO worked because SendToAsync explicitly sets saea._socketAddress to null. But there is no access to it for anybody using SocketAsyncEventArgs directly.

In the past, RemoteEndPoint was only user accessible variable and _socketAddress was always managed internally. With the new API SendTo and ReceiveFrom can use SocketAddress directly and reference would be also set on SocketAsyncEventArgs. As I realized, 1) we should make no assumption about and and we should not try to use it for anything else than just the particular call and 2) SocketAsyncEventArgs can be used directly so any related logic really needs to be at the bottom and not in the layers above.

With that I made changes to set RemoteEndPoint to null to indicate that SendTo and ReceiveFrom was invoked with user provided SocketAddress. We will also detach it from SocketAsyncEventArgs in that case so it can be re-used for another operations safely.
On other cases we can keep it around and simply override _socketAddress as we see fit instead of allocating new one every time.

@wfurtwfurt added this to the 9.0.0 milestone Feb 7, 2024
@wfurt
wfurt requested a review from a teamFebruary 7, 2024 22:47
@wfurtwfurt self-assigned this Feb 7, 2024
@ghost

ghost commented Feb 7, 2024

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

this fixes regression from #90086 and fixes #97965.

With the new SocketAddress changes the task based IO worked because SendToAsync explicitly sets saea._socketAddress to null. But there is no access to it for anybody using SocketAsyncEventArgs directly.

In the past, RemoteEndPoint was only user accessible variable and _socketAddress was always managed internally. With the new API SendTo and ReceiveFrom can use SocketAddress directly and reference would be also set on SocketAsyncEventArgs. As I realized, 1) we should make no assumption about and and we should not try to use it for anything else than just the particular call and 2) SocketAsyncEventArgs can be used directly so any related logic really needs to be at the bottom and not in the layers above.

With that I made changes to set RemoteEndPoint to null to indicate that SendTo and ReceiveFrom was invoked with user provided SocketAddress. We will also detach it from SocketAsyncEventArgs in that case so it can be re-used for another operations safely.
On other cases we can keep it around and simply override _socketAddress as we see fit instead of allocating new one every time.

Author:wfurt
Assignees:wfurt
Labels:

area-System.Net.Sockets

Milestone:9.0.0

finally
{
// detach user provided SA so we do not accidentally stomp on it later.
saea._socketAddress = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's ok to null it here because it's only used synchronously as part of the send operation and not asynchronously?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

yes. We will make _socketAddress before first try. f we do not finish synchronously on Unix, it would be copied to queued *SendOperation. For Windows, the const sockaddr *lpTo is IN for WSASendTo and AFAIK it does not need to be preserved until the overlapped IO is completed.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
if (_remoteEndPoint == null)
{
// detach user provided SA as it was updated in place.
_socketAddress = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The only two operations it would be set for are ReceiveFrom and SendTo, and we already handled the SendTo case on the synchronous start path?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

yes. For SendTo we clear it when operation starts, for ReceiveFrom we do it when the operation is finished.

@wfurt
wfurt merged commit f9637f1 into dotnet:mainFeb 27, 2024
@wfurt
wfurt deleted the SocketAsyncEventArgs branch February 27, 2024 16:50
@wfurt

Copy link
Copy Markdown
MemberAuthor

/backport to release/8.0-staging

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8268148999

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 26, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reusing the same SocketAsyncEventArgs for different udp remote endpoints does not work anymore

2 participants

@wfurt@stephentoub
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix SendTo with SocketAsyncEventArgs - #98134

Merged
wfurt merged 6 commits into
dotnet:mainfrom
wfurt:SocketAsyncEventArgs
Feb 27, 2024
Merged

fix SendTo with SocketAsyncEventArgs#98134
wfurt merged 6 commits into
dotnet:mainfrom
wfurt:SocketAsyncEventArgs

Conversation

@wfurt

@wfurtwfurt commented Feb 7, 2024

Copy link
Copy Markdown
Member

Fixes#97965 and #99863 -- a regression from PR #90086 (in 8.0).

With the new SocketAddress changes the task based IO worked because SendToAsync explicitly sets saea._socketAddress to null. But there is no access to it for anybody using SocketAsyncEventArgs directly.

In the past, RemoteEndPoint was only user accessible variable and _socketAddress was always managed internally. With the new API SendTo and ReceiveFrom can use SocketAddress directly and reference would be also set on SocketAsyncEventArgs. As I realized, 1) we should make no assumption about and and we should not try to use it for anything else than just the particular call and 2) SocketAsyncEventArgs can be used directly so any related logic really needs to be at the bottom and not in the layers above.

With that I made changes to set RemoteEndPoint to null to indicate that SendTo and ReceiveFrom was invoked with user provided SocketAddress. We will also detach it from SocketAsyncEventArgs in that case so it can be re-used for another operations safely.
On other cases we can keep it around and simply override _socketAddress as we see fit instead of allocating new one every time.

@wfurtwfurt added this to the 9.0.0 milestone Feb 7, 2024
@wfurt
wfurt requested a review from a teamFebruary 7, 2024 22:47
@wfurtwfurt self-assigned this Feb 7, 2024
@ghost

ghost commented Feb 7, 2024

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

this fixes regression from #90086 and fixes #97965.

With the new SocketAddress changes the task based IO worked because SendToAsync explicitly sets saea._socketAddress to null. But there is no access to it for anybody using SocketAsyncEventArgs directly.

In the past, RemoteEndPoint was only user accessible variable and _socketAddress was always managed internally. With the new API SendTo and ReceiveFrom can use SocketAddress directly and reference would be also set on SocketAsyncEventArgs. As I realized, 1) we should make no assumption about and and we should not try to use it for anything else than just the particular call and 2) SocketAsyncEventArgs can be used directly so any related logic really needs to be at the bottom and not in the layers above.

With that I made changes to set RemoteEndPoint to null to indicate that SendTo and ReceiveFrom was invoked with user provided SocketAddress. We will also detach it from SocketAsyncEventArgs in that case so it can be re-used for another operations safely.
On other cases we can keep it around and simply override _socketAddress as we see fit instead of allocating new one every time.

Author:wfurt
Assignees:wfurt
Labels:

area-System.Net.Sockets

Milestone:9.0.0

finally
{
// detach user provided SA so we do not accidentally stomp on it later.
saea._socketAddress = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's ok to null it here because it's only used synchronously as part of the send operation and not asynchronously?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

yes. We will make _socketAddress before first try. f we do not finish synchronously on Unix, it would be copied to queued *SendOperation. For Windows, the const sockaddr *lpTo is IN for WSASendTo and AFAIK it does not need to be preserved until the overlapped IO is completed.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
if (_remoteEndPoint == null)
{
// detach user provided SA as it was updated in place.
_socketAddress = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The only two operations it would be set for are ReceiveFrom and SendTo, and we already handled the SendTo case on the synchronous start path?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

yes. For SendTo we clear it when operation starts, for ReceiveFrom we do it when the operation is finished.

@wfurt
wfurt merged commit f9637f1 into dotnet:mainFeb 27, 2024
@wfurt
wfurt deleted the SocketAsyncEventArgs branch February 27, 2024 16:50
@wfurt

Copy link
Copy Markdown
MemberAuthor

/backport to release/8.0-staging

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8268148999

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 26, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reusing the same SocketAsyncEventArgs for different udp remote endpoints does not work anymore

2 participants

@wfurt@stephentoub
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix SendTo with SocketAsyncEventArgs - #98134

Merged
wfurt merged 6 commits into
dotnet:mainfrom
wfurt:SocketAsyncEventArgs
Feb 27, 2024
Merged

fix SendTo with SocketAsyncEventArgs#98134
wfurt merged 6 commits into
dotnet:mainfrom
wfurt:SocketAsyncEventArgs

Conversation

@wfurt

@wfurtwfurt commented Feb 7, 2024

Copy link
Copy Markdown
Member

Fixes#97965 and #99863 -- a regression from PR #90086 (in 8.0).

With the new SocketAddress changes the task based IO worked because SendToAsync explicitly sets saea._socketAddress to null. But there is no access to it for anybody using SocketAsyncEventArgs directly.

In the past, RemoteEndPoint was only user accessible variable and _socketAddress was always managed internally. With the new API SendTo and ReceiveFrom can use SocketAddress directly and reference would be also set on SocketAsyncEventArgs. As I realized, 1) we should make no assumption about and and we should not try to use it for anything else than just the particular call and 2) SocketAsyncEventArgs can be used directly so any related logic really needs to be at the bottom and not in the layers above.

With that I made changes to set RemoteEndPoint to null to indicate that SendTo and ReceiveFrom was invoked with user provided SocketAddress. We will also detach it from SocketAsyncEventArgs in that case so it can be re-used for another operations safely.
On other cases we can keep it around and simply override _socketAddress as we see fit instead of allocating new one every time.

@wfurtwfurt added this to the 9.0.0 milestone Feb 7, 2024
@wfurt
wfurt requested a review from a teamFebruary 7, 2024 22:47
@wfurtwfurt self-assigned this Feb 7, 2024
@ghost

ghost commented Feb 7, 2024

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

this fixes regression from #90086 and fixes #97965.

With the new SocketAddress changes the task based IO worked because SendToAsync explicitly sets saea._socketAddress to null. But there is no access to it for anybody using SocketAsyncEventArgs directly.

In the past, RemoteEndPoint was only user accessible variable and _socketAddress was always managed internally. With the new API SendTo and ReceiveFrom can use SocketAddress directly and reference would be also set on SocketAsyncEventArgs. As I realized, 1) we should make no assumption about and and we should not try to use it for anything else than just the particular call and 2) SocketAsyncEventArgs can be used directly so any related logic really needs to be at the bottom and not in the layers above.

With that I made changes to set RemoteEndPoint to null to indicate that SendTo and ReceiveFrom was invoked with user provided SocketAddress. We will also detach it from SocketAsyncEventArgs in that case so it can be re-used for another operations safely.
On other cases we can keep it around and simply override _socketAddress as we see fit instead of allocating new one every time.

Author:wfurt
Assignees:wfurt
Labels:

area-System.Net.Sockets

Milestone:9.0.0

finally
{
// detach user provided SA so we do not accidentally stomp on it later.
saea._socketAddress = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's ok to null it here because it's only used synchronously as part of the send operation and not asynchronously?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

yes. We will make _socketAddress before first try. f we do not finish synchronously on Unix, it would be copied to queued *SendOperation. For Windows, the const sockaddr *lpTo is IN for WSASendTo and AFAIK it does not need to be preserved until the overlapped IO is completed.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
if (_remoteEndPoint == null)
{
// detach user provided SA as it was updated in place.
_socketAddress = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The only two operations it would be set for are ReceiveFrom and SendTo, and we already handled the SendTo case on the synchronous start path?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

yes. For SendTo we clear it when operation starts, for ReceiveFrom we do it when the operation is finished.

@wfurt
wfurt merged commit f9637f1 into dotnet:mainFeb 27, 2024
@wfurt
wfurt deleted the SocketAsyncEventArgs branch February 27, 2024 16:50
@wfurt

Copy link
Copy Markdown
MemberAuthor

/backport to release/8.0-staging

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8268148999

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 26, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reusing the same SocketAsyncEventArgs for different udp remote endpoints does not work anymore

2 participants

@wfurt@stephentoub
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix SendTo with SocketAsyncEventArgs - #98134

Merged
wfurt merged 6 commits into
dotnet:mainfrom
wfurt:SocketAsyncEventArgs
Feb 27, 2024
Merged

fix SendTo with SocketAsyncEventArgs#98134
wfurt merged 6 commits into
dotnet:mainfrom
wfurt:SocketAsyncEventArgs

Conversation

@wfurt

@wfurtwfurt commented Feb 7, 2024

Copy link
Copy Markdown
Member

Fixes#97965 and #99863 -- a regression from PR #90086 (in 8.0).

With the new SocketAddress changes the task based IO worked because SendToAsync explicitly sets saea._socketAddress to null. But there is no access to it for anybody using SocketAsyncEventArgs directly.

In the past, RemoteEndPoint was only user accessible variable and _socketAddress was always managed internally. With the new API SendTo and ReceiveFrom can use SocketAddress directly and reference would be also set on SocketAsyncEventArgs. As I realized, 1) we should make no assumption about and and we should not try to use it for anything else than just the particular call and 2) SocketAsyncEventArgs can be used directly so any related logic really needs to be at the bottom and not in the layers above.

With that I made changes to set RemoteEndPoint to null to indicate that SendTo and ReceiveFrom was invoked with user provided SocketAddress. We will also detach it from SocketAsyncEventArgs in that case so it can be re-used for another operations safely.
On other cases we can keep it around and simply override _socketAddress as we see fit instead of allocating new one every time.

@wfurtwfurt added this to the 9.0.0 milestone Feb 7, 2024
@wfurt
wfurt requested a review from a teamFebruary 7, 2024 22:47
@wfurtwfurt self-assigned this Feb 7, 2024
@ghost

ghost commented Feb 7, 2024

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

this fixes regression from #90086 and fixes #97965.

With the new SocketAddress changes the task based IO worked because SendToAsync explicitly sets saea._socketAddress to null. But there is no access to it for anybody using SocketAsyncEventArgs directly.

In the past, RemoteEndPoint was only user accessible variable and _socketAddress was always managed internally. With the new API SendTo and ReceiveFrom can use SocketAddress directly and reference would be also set on SocketAsyncEventArgs. As I realized, 1) we should make no assumption about and and we should not try to use it for anything else than just the particular call and 2) SocketAsyncEventArgs can be used directly so any related logic really needs to be at the bottom and not in the layers above.

With that I made changes to set RemoteEndPoint to null to indicate that SendTo and ReceiveFrom was invoked with user provided SocketAddress. We will also detach it from SocketAsyncEventArgs in that case so it can be re-used for another operations safely.
On other cases we can keep it around and simply override _socketAddress as we see fit instead of allocating new one every time.

Author:wfurt
Assignees:wfurt
Labels:

area-System.Net.Sockets

Milestone:9.0.0

finally
{
// detach user provided SA so we do not accidentally stomp on it later.
saea._socketAddress = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's ok to null it here because it's only used synchronously as part of the send operation and not asynchronously?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

yes. We will make _socketAddress before first try. f we do not finish synchronously on Unix, it would be copied to queued *SendOperation. For Windows, the const sockaddr *lpTo is IN for WSASendTo and AFAIK it does not need to be preserved until the overlapped IO is completed.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
if (_remoteEndPoint == null)
{
// detach user provided SA as it was updated in place.
_socketAddress = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The only two operations it would be set for are ReceiveFrom and SendTo, and we already handled the SendTo case on the synchronous start path?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

yes. For SendTo we clear it when operation starts, for ReceiveFrom we do it when the operation is finished.

@wfurt
wfurt merged commit f9637f1 into dotnet:mainFeb 27, 2024
@wfurt
wfurt deleted the SocketAsyncEventArgs branch February 27, 2024 16:50
@wfurt

Copy link
Copy Markdown
MemberAuthor

/backport to release/8.0-staging

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8268148999

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 26, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reusing the same SocketAsyncEventArgs for different udp remote endpoints does not work anymore

2 participants

@wfurt@stephentoub
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix SendTo with SocketAsyncEventArgs - #98134

Merged
wfurt merged 6 commits into
dotnet:mainfrom
wfurt:SocketAsyncEventArgs
Feb 27, 2024
Merged

fix SendTo with SocketAsyncEventArgs#98134
wfurt merged 6 commits into
dotnet:mainfrom
wfurt:SocketAsyncEventArgs

Conversation

@wfurt

@wfurtwfurt commented Feb 7, 2024

Copy link
Copy Markdown
Member

Fixes#97965 and #99863 -- a regression from PR #90086 (in 8.0).

With the new SocketAddress changes the task based IO worked because SendToAsync explicitly sets saea._socketAddress to null. But there is no access to it for anybody using SocketAsyncEventArgs directly.

In the past, RemoteEndPoint was only user accessible variable and _socketAddress was always managed internally. With the new API SendTo and ReceiveFrom can use SocketAddress directly and reference would be also set on SocketAsyncEventArgs. As I realized, 1) we should make no assumption about and and we should not try to use it for anything else than just the particular call and 2) SocketAsyncEventArgs can be used directly so any related logic really needs to be at the bottom and not in the layers above.

With that I made changes to set RemoteEndPoint to null to indicate that SendTo and ReceiveFrom was invoked with user provided SocketAddress. We will also detach it from SocketAsyncEventArgs in that case so it can be re-used for another operations safely.
On other cases we can keep it around and simply override _socketAddress as we see fit instead of allocating new one every time.

@wfurtwfurt added this to the 9.0.0 milestone Feb 7, 2024
@wfurt
wfurt requested a review from a teamFebruary 7, 2024 22:47
@wfurtwfurt self-assigned this Feb 7, 2024
@ghost

ghost commented Feb 7, 2024

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

this fixes regression from #90086 and fixes #97965.

With the new SocketAddress changes the task based IO worked because SendToAsync explicitly sets saea._socketAddress to null. But there is no access to it for anybody using SocketAsyncEventArgs directly.

In the past, RemoteEndPoint was only user accessible variable and _socketAddress was always managed internally. With the new API SendTo and ReceiveFrom can use SocketAddress directly and reference would be also set on SocketAsyncEventArgs. As I realized, 1) we should make no assumption about and and we should not try to use it for anything else than just the particular call and 2) SocketAsyncEventArgs can be used directly so any related logic really needs to be at the bottom and not in the layers above.

With that I made changes to set RemoteEndPoint to null to indicate that SendTo and ReceiveFrom was invoked with user provided SocketAddress. We will also detach it from SocketAsyncEventArgs in that case so it can be re-used for another operations safely.
On other cases we can keep it around and simply override _socketAddress as we see fit instead of allocating new one every time.

Author:wfurt
Assignees:wfurt
Labels:

area-System.Net.Sockets

Milestone:9.0.0

finally
{
// detach user provided SA so we do not accidentally stomp on it later.
saea._socketAddress = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's ok to null it here because it's only used synchronously as part of the send operation and not asynchronously?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

yes. We will make _socketAddress before first try. f we do not finish synchronously on Unix, it would be copied to queued *SendOperation. For Windows, the const sockaddr *lpTo is IN for WSASendTo and AFAIK it does not need to be preserved until the overlapped IO is completed.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
if (_remoteEndPoint == null)
{
// detach user provided SA as it was updated in place.
_socketAddress = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The only two operations it would be set for are ReceiveFrom and SendTo, and we already handled the SendTo case on the synchronous start path?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

yes. For SendTo we clear it when operation starts, for ReceiveFrom we do it when the operation is finished.

@wfurt
wfurt merged commit f9637f1 into dotnet:mainFeb 27, 2024
@wfurt
wfurt deleted the SocketAsyncEventArgs branch February 27, 2024 16:50
@wfurt

Copy link
Copy Markdown
MemberAuthor

/backport to release/8.0-staging

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8268148999

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 26, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reusing the same SocketAsyncEventArgs for different udp remote endpoints does not work anymore

2 participants

@wfurt@stephentoub
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix SendTo with SocketAsyncEventArgs - #98134

Merged
wfurt merged 6 commits into
dotnet:mainfrom
wfurt:SocketAsyncEventArgs
Feb 27, 2024
Merged

fix SendTo with SocketAsyncEventArgs#98134
wfurt merged 6 commits into
dotnet:mainfrom
wfurt:SocketAsyncEventArgs

Conversation

@wfurt

@wfurtwfurt commented Feb 7, 2024

Copy link
Copy Markdown
Member

Fixes#97965 and #99863 -- a regression from PR #90086 (in 8.0).

With the new SocketAddress changes the task based IO worked because SendToAsync explicitly sets saea._socketAddress to null. But there is no access to it for anybody using SocketAsyncEventArgs directly.

In the past, RemoteEndPoint was only user accessible variable and _socketAddress was always managed internally. With the new API SendTo and ReceiveFrom can use SocketAddress directly and reference would be also set on SocketAsyncEventArgs. As I realized, 1) we should make no assumption about and and we should not try to use it for anything else than just the particular call and 2) SocketAsyncEventArgs can be used directly so any related logic really needs to be at the bottom and not in the layers above.

With that I made changes to set RemoteEndPoint to null to indicate that SendTo and ReceiveFrom was invoked with user provided SocketAddress. We will also detach it from SocketAsyncEventArgs in that case so it can be re-used for another operations safely.
On other cases we can keep it around and simply override _socketAddress as we see fit instead of allocating new one every time.

@wfurtwfurt added this to the 9.0.0 milestone Feb 7, 2024
@wfurt
wfurt requested a review from a teamFebruary 7, 2024 22:47
@wfurtwfurt self-assigned this Feb 7, 2024
@ghost

ghost commented Feb 7, 2024

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

this fixes regression from #90086 and fixes #97965.

With the new SocketAddress changes the task based IO worked because SendToAsync explicitly sets saea._socketAddress to null. But there is no access to it for anybody using SocketAsyncEventArgs directly.

In the past, RemoteEndPoint was only user accessible variable and _socketAddress was always managed internally. With the new API SendTo and ReceiveFrom can use SocketAddress directly and reference would be also set on SocketAsyncEventArgs. As I realized, 1) we should make no assumption about and and we should not try to use it for anything else than just the particular call and 2) SocketAsyncEventArgs can be used directly so any related logic really needs to be at the bottom and not in the layers above.

With that I made changes to set RemoteEndPoint to null to indicate that SendTo and ReceiveFrom was invoked with user provided SocketAddress. We will also detach it from SocketAsyncEventArgs in that case so it can be re-used for another operations safely.
On other cases we can keep it around and simply override _socketAddress as we see fit instead of allocating new one every time.

Author:wfurt
Assignees:wfurt
Labels:

area-System.Net.Sockets

Milestone:9.0.0

finally
{
// detach user provided SA so we do not accidentally stomp on it later.
saea._socketAddress = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's ok to null it here because it's only used synchronously as part of the send operation and not asynchronously?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

yes. We will make _socketAddress before first try. f we do not finish synchronously on Unix, it would be copied to queued *SendOperation. For Windows, the const sockaddr *lpTo is IN for WSASendTo and AFAIK it does not need to be preserved until the overlapped IO is completed.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
if (_remoteEndPoint == null)
{
// detach user provided SA as it was updated in place.
_socketAddress = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The only two operations it would be set for are ReceiveFrom and SendTo, and we already handled the SendTo case on the synchronous start path?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

yes. For SendTo we clear it when operation starts, for ReceiveFrom we do it when the operation is finished.

@wfurt
wfurt merged commit f9637f1 into dotnet:mainFeb 27, 2024
@wfurt
wfurt deleted the SocketAsyncEventArgs branch February 27, 2024 16:50
@wfurt

Copy link
Copy Markdown
MemberAuthor

/backport to release/8.0-staging

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8268148999

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 26, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reusing the same SocketAsyncEventArgs for different udp remote endpoints does not work anymore

2 participants

@wfurt@stephentoub
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix SendTo with SocketAsyncEventArgs - #98134

Merged
wfurt merged 6 commits into
dotnet:mainfrom
wfurt:SocketAsyncEventArgs
Feb 27, 2024
Merged

fix SendTo with SocketAsyncEventArgs#98134
wfurt merged 6 commits into
dotnet:mainfrom
wfurt:SocketAsyncEventArgs

Conversation

@wfurt

@wfurtwfurt commented Feb 7, 2024

Copy link
Copy Markdown
Member

Fixes#97965 and #99863 -- a regression from PR #90086 (in 8.0).

With the new SocketAddress changes the task based IO worked because SendToAsync explicitly sets saea._socketAddress to null. But there is no access to it for anybody using SocketAsyncEventArgs directly.

In the past, RemoteEndPoint was only user accessible variable and _socketAddress was always managed internally. With the new API SendTo and ReceiveFrom can use SocketAddress directly and reference would be also set on SocketAsyncEventArgs. As I realized, 1) we should make no assumption about and and we should not try to use it for anything else than just the particular call and 2) SocketAsyncEventArgs can be used directly so any related logic really needs to be at the bottom and not in the layers above.

With that I made changes to set RemoteEndPoint to null to indicate that SendTo and ReceiveFrom was invoked with user provided SocketAddress. We will also detach it from SocketAsyncEventArgs in that case so it can be re-used for another operations safely.
On other cases we can keep it around and simply override _socketAddress as we see fit instead of allocating new one every time.

@wfurtwfurt added this to the 9.0.0 milestone Feb 7, 2024
@wfurt
wfurt requested a review from a teamFebruary 7, 2024 22:47
@wfurtwfurt self-assigned this Feb 7, 2024
@ghost

ghost commented Feb 7, 2024

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

this fixes regression from #90086 and fixes #97965.

With the new SocketAddress changes the task based IO worked because SendToAsync explicitly sets saea._socketAddress to null. But there is no access to it for anybody using SocketAsyncEventArgs directly.

In the past, RemoteEndPoint was only user accessible variable and _socketAddress was always managed internally. With the new API SendTo and ReceiveFrom can use SocketAddress directly and reference would be also set on SocketAsyncEventArgs. As I realized, 1) we should make no assumption about and and we should not try to use it for anything else than just the particular call and 2) SocketAsyncEventArgs can be used directly so any related logic really needs to be at the bottom and not in the layers above.

With that I made changes to set RemoteEndPoint to null to indicate that SendTo and ReceiveFrom was invoked with user provided SocketAddress. We will also detach it from SocketAsyncEventArgs in that case so it can be re-used for another operations safely.
On other cases we can keep it around and simply override _socketAddress as we see fit instead of allocating new one every time.

Author:wfurt
Assignees:wfurt
Labels:

area-System.Net.Sockets

Milestone:9.0.0

finally
{
// detach user provided SA so we do not accidentally stomp on it later.
saea._socketAddress = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's ok to null it here because it's only used synchronously as part of the send operation and not asynchronously?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

yes. We will make _socketAddress before first try. f we do not finish synchronously on Unix, it would be copied to queued *SendOperation. For Windows, the const sockaddr *lpTo is IN for WSASendTo and AFAIK it does not need to be preserved until the overlapped IO is completed.

Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
Comment threadsrc/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Outdated
if (_remoteEndPoint == null)
{
// detach user provided SA as it was updated in place.
_socketAddress = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The only two operations it would be set for are ReceiveFrom and SendTo, and we already handled the SendTo case on the synchronous start path?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

yes. For SendTo we clear it when operation starts, for ReceiveFrom we do it when the operation is finished.

@wfurt
wfurt merged commit f9637f1 into dotnet:mainFeb 27, 2024
@wfurt
wfurt deleted the SocketAsyncEventArgs branch February 27, 2024 16:50
@wfurt

Copy link
Copy Markdown
MemberAuthor

/backport to release/8.0-staging

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/8268148999

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 26, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reusing the same SocketAsyncEventArgs for different udp remote endpoints does not work anymore

2 participants

@wfurt@stephentoub