NameResolutionPal.Unix enabled cancellation - #47036

Closed
gfoidl wants to merge 13 commits into
dotnet:masterfrom
gfoidl:unix-async-name-resolution_cancellation
Closed

NameResolutionPal.Unix enabled cancellation#47036
gfoidl wants to merge 13 commits into
dotnet:masterfrom
gfoidl:unix-async-name-resolution_cancellation

Conversation

@gfoidl

@gfoidlgfoidl commented Jan 15, 2021

Copy link
Copy Markdown
Member

#34633 added async support for name resolution on glibc-based Unix-distros, this PR adds cancellation.

Note

The man-page of gai_cancel states:

The request cannot be canceled if it is currently being processed; in that case, it will be handled as if gai_cancel() has never been called.

The source also shows that gai_cancel just removes the request from the queue, so the behavior might be somewhat unexpected and should be documented appropriate (where?)

@ghostghost added the area-System.Net label Jan 15, 2021
@ghost

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

#34633 added async support for name resolution on glibc-based Unix-distros, this PR adds cancellation.

Note

The man-page of gai_cancel states:

The request cannot be canceled if it is currently being processed; in that case, it will be handled as if gai_cancel() has never been called.

The source also shows that gai_cancel just removes the request from the queue, so the behavior might be somewhat unexpected and should be documented appropriate.

Author:gfoidl
Assignees:-
Labels:

area-System.Net

Milestone:-

Task task = Dns.GetHostAddressesAsync(TestSettings.UncachedHost, cts.Token);
for (int i = 0; i < numberOfRequests; ++i)
{
Task task = Dns.GetHostAddressesAsync(TestSettings.UncachedHost, cts.Token);

@gfoidlgfoidlJan 15, 2021

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.

See #43816 (comment)
If this is considered reliable enough, so that issue is fixed with this change.

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.

I'll let @wfurt comment, but this seems like at some point it's going to fail spuriously in CI.

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 seems like the TestSettings.UncachedHost is already used twice and the second use could be cached - certainly in case of systemd resolver. If we want to improve chance of failure, I think each round should use unique name. And the test was already problematic in CI.

We could also accept the reality that cancellation is best-effort and timing sensitive and verify that if task failed, OperationCanceledException is only one reason.

We could also use SkipTestException. That would not change the test run much but we could at least see reports over time.

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.

So we could do this strategy:

  1. update the tests here to use SkipTestException, so it won't break CI but we still get some data for the cancellation-tests
  2. provide a proper / more robust solution when adressing Move name resolution cancellation test into Docker #43816

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.

62f05fe adds SkipTestException. OK as proposed in the comment before?

Comment threadsrc/libraries/Native/Unix/System.Native/pal_networking.c Outdated

@wfurtwfurt left a comment

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.

LGTM

@karelz

Copy link
Copy Markdown
Member

@stephentoub any additional concerns, or can we merge?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Besides the code we should have a look on how to document the somewhat unintuitive behavior of cancellation on unix -- see top post.

@stephentoub

Copy link
Copy Markdown
Member

we should have a look on how to document the somewhat unintuitive behavior of cancellation on unix

All attempts at cancellation are best effort, and there are many places where certain sections of execution aren't interruptible by cancellation. It's unfortunate that the support provided by glibc isn't better here, but I don't think we need to or even can get into the nitty gritty of exactly what's cancelable when. Hopefully in the future this can be improved.

@stephentoub

stephentoub commented Feb 3, 2021

Copy link
Copy Markdown
Member

I do have a more general question, though. Given the limitation, is it worth it? This change adds some complication and cost; will there generally be a payoff, or will we often be in the non-cancelable case?

try
{
await Task.WhenAll(tasks);
throw new SkipTestException("GetHostAddressesAsync should fail but it did not.");

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.

No one's going to notice this, especially in CI. Could we just keep retrying until it does fail? Folks will notice hangs ;-)

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.

Like a148365?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

will we often be in the non-cancelable case?

I don't have numbers for this, but my gut feeling tells that with current implemenation in glibc, where a request is just removed from the queue, a lot of operations aren't cancelable. Especially #43816 wouldn't work ("these tests might be moved into a Docker container with a non-working DNS server that will never respond") as this will just hang.

In e.g. server environment where the queue will be flooded with requests, it's more likeley to actually cancel (= remove from the queue) a request.

TBH I don't know if it is worth it, hope that you have an answer for this 😉

@wfurt

wfurt commented Feb 5, 2021

Copy link
Copy Markdown
Member

will we often be in the non-cancelable case?

I don't have numbers for this, but my gut feeling tells that with current implemenation in glibc, where a request is just removed from the queue, a lot of operations aren't cancelable. Especially #43816 wouldn't work ("these tests might be moved into a Docker container with a non-working DNS server that will never respond") as this will just hang.

In e.g. server environment where the queue will be flooded with requests, it's more likeley to actually cancel (= remove from the queue) a request.

TBH I don't know if it is worth it, hope that you have an answer for this 😉

To me, the value of cancelation is ability to fail lookup that takes too long - for whatever reason. That gives caller option to handle that any way they want. Whether we can actually cancel operation inside glibc is secondary IMHO. Since we register delegate, could we do that somehow?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Since we register delegate, could we do that somehow?

gai_cancel returns either EAI_CANCELLED, EAI_NOTCANCELLED, or EAI_ALLDONE.
We could return this value to

Interop.Sys.CancelGetHostEntryForNameAsync(context->CancelHandle);
and then decide how to continue.

EAI_CANCELLED or EAI_ALLDONE are already handled by the current state of the PR.

EAI_NOTCANCELLED is the problematic case. We could return a canceled task the caller, but would need to keep the context alive in order to get no AV (I assume) if the native lookup completes anytime and invokes the callback

which is
privateunsafestructGetHostEntryForNameContext
{
publicInterop.Sys.HostEntryResult;
publicIntPtrState;
.

Right now I have no real idea on how to do this reliable, withou leaking memory or too much complication of the code.

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Closing as per discussion in #48566

In short: getaddrinfo_a is a sub-optimal api, that doesn't perform real async name resolution. Other ways will be explored.

@gfoidlgfoidl closed this Feb 23, 2021
@gfoidl
gfoidl deleted the unix-async-name-resolution_cancellation branch February 23, 2021 20:27
@gfoidl
gfoidl restored the unix-async-name-resolution_cancellation branch March 4, 2021 08:29
@gfoidl
gfoidl deleted the unix-async-name-resolution_cancellation branch March 4, 2021 08:31
@ghostghost locked as resolved and limited conversation to collaborators Apr 3, 2021
@karelzkarelz added this to the 6.0.0 milestone May 20, 2021
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.

4 participants

@gfoidl@karelz@stephentoub@wfurt
, '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

NameResolutionPal.Unix enabled cancellation - #47036

Closed
gfoidl wants to merge 13 commits into
dotnet:masterfrom
gfoidl:unix-async-name-resolution_cancellation
Closed

NameResolutionPal.Unix enabled cancellation#47036
gfoidl wants to merge 13 commits into
dotnet:masterfrom
gfoidl:unix-async-name-resolution_cancellation

Conversation

@gfoidl

@gfoidlgfoidl commented Jan 15, 2021

Copy link
Copy Markdown
Member

#34633 added async support for name resolution on glibc-based Unix-distros, this PR adds cancellation.

Note

The man-page of gai_cancel states:

The request cannot be canceled if it is currently being processed; in that case, it will be handled as if gai_cancel() has never been called.

The source also shows that gai_cancel just removes the request from the queue, so the behavior might be somewhat unexpected and should be documented appropriate (where?)

@ghostghost added the area-System.Net label Jan 15, 2021
@ghost

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

#34633 added async support for name resolution on glibc-based Unix-distros, this PR adds cancellation.

Note

The man-page of gai_cancel states:

The request cannot be canceled if it is currently being processed; in that case, it will be handled as if gai_cancel() has never been called.

The source also shows that gai_cancel just removes the request from the queue, so the behavior might be somewhat unexpected and should be documented appropriate.

Author:gfoidl
Assignees:-
Labels:

area-System.Net

Milestone:-

Task task = Dns.GetHostAddressesAsync(TestSettings.UncachedHost, cts.Token);
for (int i = 0; i < numberOfRequests; ++i)
{
Task task = Dns.GetHostAddressesAsync(TestSettings.UncachedHost, cts.Token);

@gfoidlgfoidlJan 15, 2021

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.

See #43816 (comment)
If this is considered reliable enough, so that issue is fixed with this change.

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.

I'll let @wfurt comment, but this seems like at some point it's going to fail spuriously in CI.

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 seems like the TestSettings.UncachedHost is already used twice and the second use could be cached - certainly in case of systemd resolver. If we want to improve chance of failure, I think each round should use unique name. And the test was already problematic in CI.

We could also accept the reality that cancellation is best-effort and timing sensitive and verify that if task failed, OperationCanceledException is only one reason.

We could also use SkipTestException. That would not change the test run much but we could at least see reports over time.

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.

So we could do this strategy:

  1. update the tests here to use SkipTestException, so it won't break CI but we still get some data for the cancellation-tests
  2. provide a proper / more robust solution when adressing Move name resolution cancellation test into Docker #43816

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.

62f05fe adds SkipTestException. OK as proposed in the comment before?

Comment threadsrc/libraries/Native/Unix/System.Native/pal_networking.c Outdated

@wfurtwfurt left a comment

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.

LGTM

@karelz

Copy link
Copy Markdown
Member

@stephentoub any additional concerns, or can we merge?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Besides the code we should have a look on how to document the somewhat unintuitive behavior of cancellation on unix -- see top post.

@stephentoub

Copy link
Copy Markdown
Member

we should have a look on how to document the somewhat unintuitive behavior of cancellation on unix

All attempts at cancellation are best effort, and there are many places where certain sections of execution aren't interruptible by cancellation. It's unfortunate that the support provided by glibc isn't better here, but I don't think we need to or even can get into the nitty gritty of exactly what's cancelable when. Hopefully in the future this can be improved.

@stephentoub

stephentoub commented Feb 3, 2021

Copy link
Copy Markdown
Member

I do have a more general question, though. Given the limitation, is it worth it? This change adds some complication and cost; will there generally be a payoff, or will we often be in the non-cancelable case?

try
{
await Task.WhenAll(tasks);
throw new SkipTestException("GetHostAddressesAsync should fail but it did not.");

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.

No one's going to notice this, especially in CI. Could we just keep retrying until it does fail? Folks will notice hangs ;-)

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.

Like a148365?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

will we often be in the non-cancelable case?

I don't have numbers for this, but my gut feeling tells that with current implemenation in glibc, where a request is just removed from the queue, a lot of operations aren't cancelable. Especially #43816 wouldn't work ("these tests might be moved into a Docker container with a non-working DNS server that will never respond") as this will just hang.

In e.g. server environment where the queue will be flooded with requests, it's more likeley to actually cancel (= remove from the queue) a request.

TBH I don't know if it is worth it, hope that you have an answer for this 😉

@wfurt

wfurt commented Feb 5, 2021

Copy link
Copy Markdown
Member

will we often be in the non-cancelable case?

I don't have numbers for this, but my gut feeling tells that with current implemenation in glibc, where a request is just removed from the queue, a lot of operations aren't cancelable. Especially #43816 wouldn't work ("these tests might be moved into a Docker container with a non-working DNS server that will never respond") as this will just hang.

In e.g. server environment where the queue will be flooded with requests, it's more likeley to actually cancel (= remove from the queue) a request.

TBH I don't know if it is worth it, hope that you have an answer for this 😉

To me, the value of cancelation is ability to fail lookup that takes too long - for whatever reason. That gives caller option to handle that any way they want. Whether we can actually cancel operation inside glibc is secondary IMHO. Since we register delegate, could we do that somehow?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Since we register delegate, could we do that somehow?

gai_cancel returns either EAI_CANCELLED, EAI_NOTCANCELLED, or EAI_ALLDONE.
We could return this value to

Interop.Sys.CancelGetHostEntryForNameAsync(context->CancelHandle);
and then decide how to continue.

EAI_CANCELLED or EAI_ALLDONE are already handled by the current state of the PR.

EAI_NOTCANCELLED is the problematic case. We could return a canceled task the caller, but would need to keep the context alive in order to get no AV (I assume) if the native lookup completes anytime and invokes the callback

which is
privateunsafestructGetHostEntryForNameContext
{
publicInterop.Sys.HostEntryResult;
publicIntPtrState;
.

Right now I have no real idea on how to do this reliable, withou leaking memory or too much complication of the code.

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Closing as per discussion in #48566

In short: getaddrinfo_a is a sub-optimal api, that doesn't perform real async name resolution. Other ways will be explored.

@gfoidlgfoidl closed this Feb 23, 2021
@gfoidl
gfoidl deleted the unix-async-name-resolution_cancellation branch February 23, 2021 20:27
@gfoidl
gfoidl restored the unix-async-name-resolution_cancellation branch March 4, 2021 08:29
@gfoidl
gfoidl deleted the unix-async-name-resolution_cancellation branch March 4, 2021 08:31
@ghostghost locked as resolved and limited conversation to collaborators Apr 3, 2021
@karelzkarelz added this to the 6.0.0 milestone May 20, 2021
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.

4 participants

@gfoidl@karelz@stephentoub@wfurt
, '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

NameResolutionPal.Unix enabled cancellation - #47036

Closed
gfoidl wants to merge 13 commits into
dotnet:masterfrom
gfoidl:unix-async-name-resolution_cancellation
Closed

NameResolutionPal.Unix enabled cancellation#47036
gfoidl wants to merge 13 commits into
dotnet:masterfrom
gfoidl:unix-async-name-resolution_cancellation

Conversation

@gfoidl

@gfoidlgfoidl commented Jan 15, 2021

Copy link
Copy Markdown
Member

#34633 added async support for name resolution on glibc-based Unix-distros, this PR adds cancellation.

Note

The man-page of gai_cancel states:

The request cannot be canceled if it is currently being processed; in that case, it will be handled as if gai_cancel() has never been called.

The source also shows that gai_cancel just removes the request from the queue, so the behavior might be somewhat unexpected and should be documented appropriate (where?)

@ghostghost added the area-System.Net label Jan 15, 2021
@ghost

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

#34633 added async support for name resolution on glibc-based Unix-distros, this PR adds cancellation.

Note

The man-page of gai_cancel states:

The request cannot be canceled if it is currently being processed; in that case, it will be handled as if gai_cancel() has never been called.

The source also shows that gai_cancel just removes the request from the queue, so the behavior might be somewhat unexpected and should be documented appropriate.

Author:gfoidl
Assignees:-
Labels:

area-System.Net

Milestone:-

Task task = Dns.GetHostAddressesAsync(TestSettings.UncachedHost, cts.Token);
for (int i = 0; i < numberOfRequests; ++i)
{
Task task = Dns.GetHostAddressesAsync(TestSettings.UncachedHost, cts.Token);

@gfoidlgfoidlJan 15, 2021

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.

See #43816 (comment)
If this is considered reliable enough, so that issue is fixed with this change.

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.

I'll let @wfurt comment, but this seems like at some point it's going to fail spuriously in CI.

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 seems like the TestSettings.UncachedHost is already used twice and the second use could be cached - certainly in case of systemd resolver. If we want to improve chance of failure, I think each round should use unique name. And the test was already problematic in CI.

We could also accept the reality that cancellation is best-effort and timing sensitive and verify that if task failed, OperationCanceledException is only one reason.

We could also use SkipTestException. That would not change the test run much but we could at least see reports over time.

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.

So we could do this strategy:

  1. update the tests here to use SkipTestException, so it won't break CI but we still get some data for the cancellation-tests
  2. provide a proper / more robust solution when adressing Move name resolution cancellation test into Docker #43816

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.

62f05fe adds SkipTestException. OK as proposed in the comment before?

Comment threadsrc/libraries/Native/Unix/System.Native/pal_networking.c Outdated

@wfurtwfurt left a comment

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.

LGTM

@karelz

Copy link
Copy Markdown
Member

@stephentoub any additional concerns, or can we merge?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Besides the code we should have a look on how to document the somewhat unintuitive behavior of cancellation on unix -- see top post.

@stephentoub

Copy link
Copy Markdown
Member

we should have a look on how to document the somewhat unintuitive behavior of cancellation on unix

All attempts at cancellation are best effort, and there are many places where certain sections of execution aren't interruptible by cancellation. It's unfortunate that the support provided by glibc isn't better here, but I don't think we need to or even can get into the nitty gritty of exactly what's cancelable when. Hopefully in the future this can be improved.

@stephentoub

stephentoub commented Feb 3, 2021

Copy link
Copy Markdown
Member

I do have a more general question, though. Given the limitation, is it worth it? This change adds some complication and cost; will there generally be a payoff, or will we often be in the non-cancelable case?

try
{
await Task.WhenAll(tasks);
throw new SkipTestException("GetHostAddressesAsync should fail but it did not.");

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.

No one's going to notice this, especially in CI. Could we just keep retrying until it does fail? Folks will notice hangs ;-)

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.

Like a148365?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

will we often be in the non-cancelable case?

I don't have numbers for this, but my gut feeling tells that with current implemenation in glibc, where a request is just removed from the queue, a lot of operations aren't cancelable. Especially #43816 wouldn't work ("these tests might be moved into a Docker container with a non-working DNS server that will never respond") as this will just hang.

In e.g. server environment where the queue will be flooded with requests, it's more likeley to actually cancel (= remove from the queue) a request.

TBH I don't know if it is worth it, hope that you have an answer for this 😉

@wfurt

wfurt commented Feb 5, 2021

Copy link
Copy Markdown
Member

will we often be in the non-cancelable case?

I don't have numbers for this, but my gut feeling tells that with current implemenation in glibc, where a request is just removed from the queue, a lot of operations aren't cancelable. Especially #43816 wouldn't work ("these tests might be moved into a Docker container with a non-working DNS server that will never respond") as this will just hang.

In e.g. server environment where the queue will be flooded with requests, it's more likeley to actually cancel (= remove from the queue) a request.

TBH I don't know if it is worth it, hope that you have an answer for this 😉

To me, the value of cancelation is ability to fail lookup that takes too long - for whatever reason. That gives caller option to handle that any way they want. Whether we can actually cancel operation inside glibc is secondary IMHO. Since we register delegate, could we do that somehow?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Since we register delegate, could we do that somehow?

gai_cancel returns either EAI_CANCELLED, EAI_NOTCANCELLED, or EAI_ALLDONE.
We could return this value to

Interop.Sys.CancelGetHostEntryForNameAsync(context->CancelHandle);
and then decide how to continue.

EAI_CANCELLED or EAI_ALLDONE are already handled by the current state of the PR.

EAI_NOTCANCELLED is the problematic case. We could return a canceled task the caller, but would need to keep the context alive in order to get no AV (I assume) if the native lookup completes anytime and invokes the callback

which is
privateunsafestructGetHostEntryForNameContext
{
publicInterop.Sys.HostEntryResult;
publicIntPtrState;
.

Right now I have no real idea on how to do this reliable, withou leaking memory or too much complication of the code.

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Closing as per discussion in #48566

In short: getaddrinfo_a is a sub-optimal api, that doesn't perform real async name resolution. Other ways will be explored.

@gfoidlgfoidl closed this Feb 23, 2021
@gfoidl
gfoidl deleted the unix-async-name-resolution_cancellation branch February 23, 2021 20:27
@gfoidl
gfoidl restored the unix-async-name-resolution_cancellation branch March 4, 2021 08:29
@gfoidl
gfoidl deleted the unix-async-name-resolution_cancellation branch March 4, 2021 08:31
@ghostghost locked as resolved and limited conversation to collaborators Apr 3, 2021
@karelzkarelz added this to the 6.0.0 milestone May 20, 2021
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.

4 participants

@gfoidl@karelz@stephentoub@wfurt
, '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

NameResolutionPal.Unix enabled cancellation - #47036

Closed
gfoidl wants to merge 13 commits into
dotnet:masterfrom
gfoidl:unix-async-name-resolution_cancellation
Closed

NameResolutionPal.Unix enabled cancellation#47036
gfoidl wants to merge 13 commits into
dotnet:masterfrom
gfoidl:unix-async-name-resolution_cancellation

Conversation

@gfoidl

@gfoidlgfoidl commented Jan 15, 2021

Copy link
Copy Markdown
Member

#34633 added async support for name resolution on glibc-based Unix-distros, this PR adds cancellation.

Note

The man-page of gai_cancel states:

The request cannot be canceled if it is currently being processed; in that case, it will be handled as if gai_cancel() has never been called.

The source also shows that gai_cancel just removes the request from the queue, so the behavior might be somewhat unexpected and should be documented appropriate (where?)

@ghostghost added the area-System.Net label Jan 15, 2021
@ghost

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

#34633 added async support for name resolution on glibc-based Unix-distros, this PR adds cancellation.

Note

The man-page of gai_cancel states:

The request cannot be canceled if it is currently being processed; in that case, it will be handled as if gai_cancel() has never been called.

The source also shows that gai_cancel just removes the request from the queue, so the behavior might be somewhat unexpected and should be documented appropriate.

Author:gfoidl
Assignees:-
Labels:

area-System.Net

Milestone:-

Task task = Dns.GetHostAddressesAsync(TestSettings.UncachedHost, cts.Token);
for (int i = 0; i < numberOfRequests; ++i)
{
Task task = Dns.GetHostAddressesAsync(TestSettings.UncachedHost, cts.Token);

@gfoidlgfoidlJan 15, 2021

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.

See #43816 (comment)
If this is considered reliable enough, so that issue is fixed with this change.

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.

I'll let @wfurt comment, but this seems like at some point it's going to fail spuriously in CI.

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 seems like the TestSettings.UncachedHost is already used twice and the second use could be cached - certainly in case of systemd resolver. If we want to improve chance of failure, I think each round should use unique name. And the test was already problematic in CI.

We could also accept the reality that cancellation is best-effort and timing sensitive and verify that if task failed, OperationCanceledException is only one reason.

We could also use SkipTestException. That would not change the test run much but we could at least see reports over time.

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.

So we could do this strategy:

  1. update the tests here to use SkipTestException, so it won't break CI but we still get some data for the cancellation-tests
  2. provide a proper / more robust solution when adressing Move name resolution cancellation test into Docker #43816

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.

62f05fe adds SkipTestException. OK as proposed in the comment before?

Comment threadsrc/libraries/Native/Unix/System.Native/pal_networking.c Outdated

@wfurtwfurt left a comment

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.

LGTM

@karelz

Copy link
Copy Markdown
Member

@stephentoub any additional concerns, or can we merge?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Besides the code we should have a look on how to document the somewhat unintuitive behavior of cancellation on unix -- see top post.

@stephentoub

Copy link
Copy Markdown
Member

we should have a look on how to document the somewhat unintuitive behavior of cancellation on unix

All attempts at cancellation are best effort, and there are many places where certain sections of execution aren't interruptible by cancellation. It's unfortunate that the support provided by glibc isn't better here, but I don't think we need to or even can get into the nitty gritty of exactly what's cancelable when. Hopefully in the future this can be improved.

@stephentoub

stephentoub commented Feb 3, 2021

Copy link
Copy Markdown
Member

I do have a more general question, though. Given the limitation, is it worth it? This change adds some complication and cost; will there generally be a payoff, or will we often be in the non-cancelable case?

try
{
await Task.WhenAll(tasks);
throw new SkipTestException("GetHostAddressesAsync should fail but it did not.");

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.

No one's going to notice this, especially in CI. Could we just keep retrying until it does fail? Folks will notice hangs ;-)

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.

Like a148365?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

will we often be in the non-cancelable case?

I don't have numbers for this, but my gut feeling tells that with current implemenation in glibc, where a request is just removed from the queue, a lot of operations aren't cancelable. Especially #43816 wouldn't work ("these tests might be moved into a Docker container with a non-working DNS server that will never respond") as this will just hang.

In e.g. server environment where the queue will be flooded with requests, it's more likeley to actually cancel (= remove from the queue) a request.

TBH I don't know if it is worth it, hope that you have an answer for this 😉

@wfurt

wfurt commented Feb 5, 2021

Copy link
Copy Markdown
Member

will we often be in the non-cancelable case?

I don't have numbers for this, but my gut feeling tells that with current implemenation in glibc, where a request is just removed from the queue, a lot of operations aren't cancelable. Especially #43816 wouldn't work ("these tests might be moved into a Docker container with a non-working DNS server that will never respond") as this will just hang.

In e.g. server environment where the queue will be flooded with requests, it's more likeley to actually cancel (= remove from the queue) a request.

TBH I don't know if it is worth it, hope that you have an answer for this 😉

To me, the value of cancelation is ability to fail lookup that takes too long - for whatever reason. That gives caller option to handle that any way they want. Whether we can actually cancel operation inside glibc is secondary IMHO. Since we register delegate, could we do that somehow?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Since we register delegate, could we do that somehow?

gai_cancel returns either EAI_CANCELLED, EAI_NOTCANCELLED, or EAI_ALLDONE.
We could return this value to

Interop.Sys.CancelGetHostEntryForNameAsync(context->CancelHandle);
and then decide how to continue.

EAI_CANCELLED or EAI_ALLDONE are already handled by the current state of the PR.

EAI_NOTCANCELLED is the problematic case. We could return a canceled task the caller, but would need to keep the context alive in order to get no AV (I assume) if the native lookup completes anytime and invokes the callback

which is
privateunsafestructGetHostEntryForNameContext
{
publicInterop.Sys.HostEntryResult;
publicIntPtrState;
.

Right now I have no real idea on how to do this reliable, withou leaking memory or too much complication of the code.

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Closing as per discussion in #48566

In short: getaddrinfo_a is a sub-optimal api, that doesn't perform real async name resolution. Other ways will be explored.

@gfoidlgfoidl closed this Feb 23, 2021
@gfoidl
gfoidl deleted the unix-async-name-resolution_cancellation branch February 23, 2021 20:27
@gfoidl
gfoidl restored the unix-async-name-resolution_cancellation branch March 4, 2021 08:29
@gfoidl
gfoidl deleted the unix-async-name-resolution_cancellation branch March 4, 2021 08:31
@ghostghost locked as resolved and limited conversation to collaborators Apr 3, 2021
@karelzkarelz added this to the 6.0.0 milestone May 20, 2021
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.

4 participants

@gfoidl@karelz@stephentoub@wfurt
, '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

NameResolutionPal.Unix enabled cancellation - #47036

Closed
gfoidl wants to merge 13 commits into
dotnet:masterfrom
gfoidl:unix-async-name-resolution_cancellation
Closed

NameResolutionPal.Unix enabled cancellation#47036
gfoidl wants to merge 13 commits into
dotnet:masterfrom
gfoidl:unix-async-name-resolution_cancellation

Conversation

@gfoidl

@gfoidlgfoidl commented Jan 15, 2021

Copy link
Copy Markdown
Member

#34633 added async support for name resolution on glibc-based Unix-distros, this PR adds cancellation.

Note

The man-page of gai_cancel states:

The request cannot be canceled if it is currently being processed; in that case, it will be handled as if gai_cancel() has never been called.

The source also shows that gai_cancel just removes the request from the queue, so the behavior might be somewhat unexpected and should be documented appropriate (where?)

@ghostghost added the area-System.Net label Jan 15, 2021
@ghost

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

#34633 added async support for name resolution on glibc-based Unix-distros, this PR adds cancellation.

Note

The man-page of gai_cancel states:

The request cannot be canceled if it is currently being processed; in that case, it will be handled as if gai_cancel() has never been called.

The source also shows that gai_cancel just removes the request from the queue, so the behavior might be somewhat unexpected and should be documented appropriate.

Author:gfoidl
Assignees:-
Labels:

area-System.Net

Milestone:-

Task task = Dns.GetHostAddressesAsync(TestSettings.UncachedHost, cts.Token);
for (int i = 0; i < numberOfRequests; ++i)
{
Task task = Dns.GetHostAddressesAsync(TestSettings.UncachedHost, cts.Token);

@gfoidlgfoidlJan 15, 2021

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.

See #43816 (comment)
If this is considered reliable enough, so that issue is fixed with this change.

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.

I'll let @wfurt comment, but this seems like at some point it's going to fail spuriously in CI.

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 seems like the TestSettings.UncachedHost is already used twice and the second use could be cached - certainly in case of systemd resolver. If we want to improve chance of failure, I think each round should use unique name. And the test was already problematic in CI.

We could also accept the reality that cancellation is best-effort and timing sensitive and verify that if task failed, OperationCanceledException is only one reason.

We could also use SkipTestException. That would not change the test run much but we could at least see reports over time.

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.

So we could do this strategy:

  1. update the tests here to use SkipTestException, so it won't break CI but we still get some data for the cancellation-tests
  2. provide a proper / more robust solution when adressing Move name resolution cancellation test into Docker #43816

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.

62f05fe adds SkipTestException. OK as proposed in the comment before?

Comment threadsrc/libraries/Native/Unix/System.Native/pal_networking.c Outdated

@wfurtwfurt left a comment

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.

LGTM

@karelz

Copy link
Copy Markdown
Member

@stephentoub any additional concerns, or can we merge?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Besides the code we should have a look on how to document the somewhat unintuitive behavior of cancellation on unix -- see top post.

@stephentoub

Copy link
Copy Markdown
Member

we should have a look on how to document the somewhat unintuitive behavior of cancellation on unix

All attempts at cancellation are best effort, and there are many places where certain sections of execution aren't interruptible by cancellation. It's unfortunate that the support provided by glibc isn't better here, but I don't think we need to or even can get into the nitty gritty of exactly what's cancelable when. Hopefully in the future this can be improved.

@stephentoub

stephentoub commented Feb 3, 2021

Copy link
Copy Markdown
Member

I do have a more general question, though. Given the limitation, is it worth it? This change adds some complication and cost; will there generally be a payoff, or will we often be in the non-cancelable case?

try
{
await Task.WhenAll(tasks);
throw new SkipTestException("GetHostAddressesAsync should fail but it did not.");

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.

No one's going to notice this, especially in CI. Could we just keep retrying until it does fail? Folks will notice hangs ;-)

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.

Like a148365?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

will we often be in the non-cancelable case?

I don't have numbers for this, but my gut feeling tells that with current implemenation in glibc, where a request is just removed from the queue, a lot of operations aren't cancelable. Especially #43816 wouldn't work ("these tests might be moved into a Docker container with a non-working DNS server that will never respond") as this will just hang.

In e.g. server environment where the queue will be flooded with requests, it's more likeley to actually cancel (= remove from the queue) a request.

TBH I don't know if it is worth it, hope that you have an answer for this 😉

@wfurt

wfurt commented Feb 5, 2021

Copy link
Copy Markdown
Member

will we often be in the non-cancelable case?

I don't have numbers for this, but my gut feeling tells that with current implemenation in glibc, where a request is just removed from the queue, a lot of operations aren't cancelable. Especially #43816 wouldn't work ("these tests might be moved into a Docker container with a non-working DNS server that will never respond") as this will just hang.

In e.g. server environment where the queue will be flooded with requests, it's more likeley to actually cancel (= remove from the queue) a request.

TBH I don't know if it is worth it, hope that you have an answer for this 😉

To me, the value of cancelation is ability to fail lookup that takes too long - for whatever reason. That gives caller option to handle that any way they want. Whether we can actually cancel operation inside glibc is secondary IMHO. Since we register delegate, could we do that somehow?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Since we register delegate, could we do that somehow?

gai_cancel returns either EAI_CANCELLED, EAI_NOTCANCELLED, or EAI_ALLDONE.
We could return this value to

Interop.Sys.CancelGetHostEntryForNameAsync(context->CancelHandle);
and then decide how to continue.

EAI_CANCELLED or EAI_ALLDONE are already handled by the current state of the PR.

EAI_NOTCANCELLED is the problematic case. We could return a canceled task the caller, but would need to keep the context alive in order to get no AV (I assume) if the native lookup completes anytime and invokes the callback

which is
privateunsafestructGetHostEntryForNameContext
{
publicInterop.Sys.HostEntryResult;
publicIntPtrState;
.

Right now I have no real idea on how to do this reliable, withou leaking memory or too much complication of the code.

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Closing as per discussion in #48566

In short: getaddrinfo_a is a sub-optimal api, that doesn't perform real async name resolution. Other ways will be explored.

@gfoidlgfoidl closed this Feb 23, 2021
@gfoidl
gfoidl deleted the unix-async-name-resolution_cancellation branch February 23, 2021 20:27
@gfoidl
gfoidl restored the unix-async-name-resolution_cancellation branch March 4, 2021 08:29
@gfoidl
gfoidl deleted the unix-async-name-resolution_cancellation branch March 4, 2021 08:31
@ghostghost locked as resolved and limited conversation to collaborators Apr 3, 2021
@karelzkarelz added this to the 6.0.0 milestone May 20, 2021
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.

4 participants

@gfoidl@karelz@stephentoub@wfurt
, '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

NameResolutionPal.Unix enabled cancellation - #47036

Closed
gfoidl wants to merge 13 commits into
dotnet:masterfrom
gfoidl:unix-async-name-resolution_cancellation
Closed

NameResolutionPal.Unix enabled cancellation#47036
gfoidl wants to merge 13 commits into
dotnet:masterfrom
gfoidl:unix-async-name-resolution_cancellation

Conversation

@gfoidl

@gfoidlgfoidl commented Jan 15, 2021

Copy link
Copy Markdown
Member

#34633 added async support for name resolution on glibc-based Unix-distros, this PR adds cancellation.

Note

The man-page of gai_cancel states:

The request cannot be canceled if it is currently being processed; in that case, it will be handled as if gai_cancel() has never been called.

The source also shows that gai_cancel just removes the request from the queue, so the behavior might be somewhat unexpected and should be documented appropriate (where?)

@ghostghost added the area-System.Net label Jan 15, 2021
@ghost

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

#34633 added async support for name resolution on glibc-based Unix-distros, this PR adds cancellation.

Note

The man-page of gai_cancel states:

The request cannot be canceled if it is currently being processed; in that case, it will be handled as if gai_cancel() has never been called.

The source also shows that gai_cancel just removes the request from the queue, so the behavior might be somewhat unexpected and should be documented appropriate.

Author:gfoidl
Assignees:-
Labels:

area-System.Net

Milestone:-

Task task = Dns.GetHostAddressesAsync(TestSettings.UncachedHost, cts.Token);
for (int i = 0; i < numberOfRequests; ++i)
{
Task task = Dns.GetHostAddressesAsync(TestSettings.UncachedHost, cts.Token);

@gfoidlgfoidlJan 15, 2021

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.

See #43816 (comment)
If this is considered reliable enough, so that issue is fixed with this change.

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.

I'll let @wfurt comment, but this seems like at some point it's going to fail spuriously in CI.

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 seems like the TestSettings.UncachedHost is already used twice and the second use could be cached - certainly in case of systemd resolver. If we want to improve chance of failure, I think each round should use unique name. And the test was already problematic in CI.

We could also accept the reality that cancellation is best-effort and timing sensitive and verify that if task failed, OperationCanceledException is only one reason.

We could also use SkipTestException. That would not change the test run much but we could at least see reports over time.

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.

So we could do this strategy:

  1. update the tests here to use SkipTestException, so it won't break CI but we still get some data for the cancellation-tests
  2. provide a proper / more robust solution when adressing Move name resolution cancellation test into Docker #43816

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.

62f05fe adds SkipTestException. OK as proposed in the comment before?

Comment threadsrc/libraries/Native/Unix/System.Native/pal_networking.c Outdated

@wfurtwfurt left a comment

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.

LGTM

@karelz

Copy link
Copy Markdown
Member

@stephentoub any additional concerns, or can we merge?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Besides the code we should have a look on how to document the somewhat unintuitive behavior of cancellation on unix -- see top post.

@stephentoub

Copy link
Copy Markdown
Member

we should have a look on how to document the somewhat unintuitive behavior of cancellation on unix

All attempts at cancellation are best effort, and there are many places where certain sections of execution aren't interruptible by cancellation. It's unfortunate that the support provided by glibc isn't better here, but I don't think we need to or even can get into the nitty gritty of exactly what's cancelable when. Hopefully in the future this can be improved.

@stephentoub

stephentoub commented Feb 3, 2021

Copy link
Copy Markdown
Member

I do have a more general question, though. Given the limitation, is it worth it? This change adds some complication and cost; will there generally be a payoff, or will we often be in the non-cancelable case?

try
{
await Task.WhenAll(tasks);
throw new SkipTestException("GetHostAddressesAsync should fail but it did not.");

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.

No one's going to notice this, especially in CI. Could we just keep retrying until it does fail? Folks will notice hangs ;-)

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.

Like a148365?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

will we often be in the non-cancelable case?

I don't have numbers for this, but my gut feeling tells that with current implemenation in glibc, where a request is just removed from the queue, a lot of operations aren't cancelable. Especially #43816 wouldn't work ("these tests might be moved into a Docker container with a non-working DNS server that will never respond") as this will just hang.

In e.g. server environment where the queue will be flooded with requests, it's more likeley to actually cancel (= remove from the queue) a request.

TBH I don't know if it is worth it, hope that you have an answer for this 😉

@wfurt

wfurt commented Feb 5, 2021

Copy link
Copy Markdown
Member

will we often be in the non-cancelable case?

I don't have numbers for this, but my gut feeling tells that with current implemenation in glibc, where a request is just removed from the queue, a lot of operations aren't cancelable. Especially #43816 wouldn't work ("these tests might be moved into a Docker container with a non-working DNS server that will never respond") as this will just hang.

In e.g. server environment where the queue will be flooded with requests, it's more likeley to actually cancel (= remove from the queue) a request.

TBH I don't know if it is worth it, hope that you have an answer for this 😉

To me, the value of cancelation is ability to fail lookup that takes too long - for whatever reason. That gives caller option to handle that any way they want. Whether we can actually cancel operation inside glibc is secondary IMHO. Since we register delegate, could we do that somehow?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Since we register delegate, could we do that somehow?

gai_cancel returns either EAI_CANCELLED, EAI_NOTCANCELLED, or EAI_ALLDONE.
We could return this value to

Interop.Sys.CancelGetHostEntryForNameAsync(context->CancelHandle);
and then decide how to continue.

EAI_CANCELLED or EAI_ALLDONE are already handled by the current state of the PR.

EAI_NOTCANCELLED is the problematic case. We could return a canceled task the caller, but would need to keep the context alive in order to get no AV (I assume) if the native lookup completes anytime and invokes the callback

which is
privateunsafestructGetHostEntryForNameContext
{
publicInterop.Sys.HostEntryResult;
publicIntPtrState;
.

Right now I have no real idea on how to do this reliable, withou leaking memory or too much complication of the code.

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Closing as per discussion in #48566

In short: getaddrinfo_a is a sub-optimal api, that doesn't perform real async name resolution. Other ways will be explored.

@gfoidlgfoidl closed this Feb 23, 2021
@gfoidl
gfoidl deleted the unix-async-name-resolution_cancellation branch February 23, 2021 20:27
@gfoidl
gfoidl restored the unix-async-name-resolution_cancellation branch March 4, 2021 08:29
@gfoidl
gfoidl deleted the unix-async-name-resolution_cancellation branch March 4, 2021 08:31
@ghostghost locked as resolved and limited conversation to collaborators Apr 3, 2021
@karelzkarelz added this to the 6.0.0 milestone May 20, 2021
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.

4 participants

@gfoidl@karelz@stephentoub@wfurt
, '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

NameResolutionPal.Unix enabled cancellation - #47036

Closed
gfoidl wants to merge 13 commits into
dotnet:masterfrom
gfoidl:unix-async-name-resolution_cancellation
Closed

NameResolutionPal.Unix enabled cancellation#47036
gfoidl wants to merge 13 commits into
dotnet:masterfrom
gfoidl:unix-async-name-resolution_cancellation

Conversation

@gfoidl

@gfoidlgfoidl commented Jan 15, 2021

Copy link
Copy Markdown
Member

#34633 added async support for name resolution on glibc-based Unix-distros, this PR adds cancellation.

Note

The man-page of gai_cancel states:

The request cannot be canceled if it is currently being processed; in that case, it will be handled as if gai_cancel() has never been called.

The source also shows that gai_cancel just removes the request from the queue, so the behavior might be somewhat unexpected and should be documented appropriate (where?)

@ghostghost added the area-System.Net label Jan 15, 2021
@ghost

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

#34633 added async support for name resolution on glibc-based Unix-distros, this PR adds cancellation.

Note

The man-page of gai_cancel states:

The request cannot be canceled if it is currently being processed; in that case, it will be handled as if gai_cancel() has never been called.

The source also shows that gai_cancel just removes the request from the queue, so the behavior might be somewhat unexpected and should be documented appropriate.

Author:gfoidl
Assignees:-
Labels:

area-System.Net

Milestone:-

Task task = Dns.GetHostAddressesAsync(TestSettings.UncachedHost, cts.Token);
for (int i = 0; i < numberOfRequests; ++i)
{
Task task = Dns.GetHostAddressesAsync(TestSettings.UncachedHost, cts.Token);

@gfoidlgfoidlJan 15, 2021

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.

See #43816 (comment)
If this is considered reliable enough, so that issue is fixed with this change.

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.

I'll let @wfurt comment, but this seems like at some point it's going to fail spuriously in CI.

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 seems like the TestSettings.UncachedHost is already used twice and the second use could be cached - certainly in case of systemd resolver. If we want to improve chance of failure, I think each round should use unique name. And the test was already problematic in CI.

We could also accept the reality that cancellation is best-effort and timing sensitive and verify that if task failed, OperationCanceledException is only one reason.

We could also use SkipTestException. That would not change the test run much but we could at least see reports over time.

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.

So we could do this strategy:

  1. update the tests here to use SkipTestException, so it won't break CI but we still get some data for the cancellation-tests
  2. provide a proper / more robust solution when adressing Move name resolution cancellation test into Docker #43816

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.

62f05fe adds SkipTestException. OK as proposed in the comment before?

Comment threadsrc/libraries/Native/Unix/System.Native/pal_networking.c Outdated

@wfurtwfurt left a comment

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.

LGTM

@karelz

Copy link
Copy Markdown
Member

@stephentoub any additional concerns, or can we merge?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Besides the code we should have a look on how to document the somewhat unintuitive behavior of cancellation on unix -- see top post.

@stephentoub

Copy link
Copy Markdown
Member

we should have a look on how to document the somewhat unintuitive behavior of cancellation on unix

All attempts at cancellation are best effort, and there are many places where certain sections of execution aren't interruptible by cancellation. It's unfortunate that the support provided by glibc isn't better here, but I don't think we need to or even can get into the nitty gritty of exactly what's cancelable when. Hopefully in the future this can be improved.

@stephentoub

stephentoub commented Feb 3, 2021

Copy link
Copy Markdown
Member

I do have a more general question, though. Given the limitation, is it worth it? This change adds some complication and cost; will there generally be a payoff, or will we often be in the non-cancelable case?

try
{
await Task.WhenAll(tasks);
throw new SkipTestException("GetHostAddressesAsync should fail but it did not.");

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.

No one's going to notice this, especially in CI. Could we just keep retrying until it does fail? Folks will notice hangs ;-)

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.

Like a148365?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

will we often be in the non-cancelable case?

I don't have numbers for this, but my gut feeling tells that with current implemenation in glibc, where a request is just removed from the queue, a lot of operations aren't cancelable. Especially #43816 wouldn't work ("these tests might be moved into a Docker container with a non-working DNS server that will never respond") as this will just hang.

In e.g. server environment where the queue will be flooded with requests, it's more likeley to actually cancel (= remove from the queue) a request.

TBH I don't know if it is worth it, hope that you have an answer for this 😉

@wfurt

wfurt commented Feb 5, 2021

Copy link
Copy Markdown
Member

will we often be in the non-cancelable case?

I don't have numbers for this, but my gut feeling tells that with current implemenation in glibc, where a request is just removed from the queue, a lot of operations aren't cancelable. Especially #43816 wouldn't work ("these tests might be moved into a Docker container with a non-working DNS server that will never respond") as this will just hang.

In e.g. server environment where the queue will be flooded with requests, it's more likeley to actually cancel (= remove from the queue) a request.

TBH I don't know if it is worth it, hope that you have an answer for this 😉

To me, the value of cancelation is ability to fail lookup that takes too long - for whatever reason. That gives caller option to handle that any way they want. Whether we can actually cancel operation inside glibc is secondary IMHO. Since we register delegate, could we do that somehow?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Since we register delegate, could we do that somehow?

gai_cancel returns either EAI_CANCELLED, EAI_NOTCANCELLED, or EAI_ALLDONE.
We could return this value to

Interop.Sys.CancelGetHostEntryForNameAsync(context->CancelHandle);
and then decide how to continue.

EAI_CANCELLED or EAI_ALLDONE are already handled by the current state of the PR.

EAI_NOTCANCELLED is the problematic case. We could return a canceled task the caller, but would need to keep the context alive in order to get no AV (I assume) if the native lookup completes anytime and invokes the callback

which is
privateunsafestructGetHostEntryForNameContext
{
publicInterop.Sys.HostEntryResult;
publicIntPtrState;
.

Right now I have no real idea on how to do this reliable, withou leaking memory or too much complication of the code.

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Closing as per discussion in #48566

In short: getaddrinfo_a is a sub-optimal api, that doesn't perform real async name resolution. Other ways will be explored.

@gfoidlgfoidl closed this Feb 23, 2021
@gfoidl
gfoidl deleted the unix-async-name-resolution_cancellation branch February 23, 2021 20:27
@gfoidl
gfoidl restored the unix-async-name-resolution_cancellation branch March 4, 2021 08:29
@gfoidl
gfoidl deleted the unix-async-name-resolution_cancellation branch March 4, 2021 08:31
@ghostghost locked as resolved and limited conversation to collaborators Apr 3, 2021
@karelzkarelz added this to the 6.0.0 milestone May 20, 2021
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.

4 participants

@gfoidl@karelz@stephentoub@wfurt
, '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

NameResolutionPal.Unix enabled cancellation - #47036

Closed
gfoidl wants to merge 13 commits into
dotnet:masterfrom
gfoidl:unix-async-name-resolution_cancellation
Closed

NameResolutionPal.Unix enabled cancellation#47036
gfoidl wants to merge 13 commits into
dotnet:masterfrom
gfoidl:unix-async-name-resolution_cancellation

Conversation

@gfoidl

@gfoidlgfoidl commented Jan 15, 2021

Copy link
Copy Markdown
Member

#34633 added async support for name resolution on glibc-based Unix-distros, this PR adds cancellation.

Note

The man-page of gai_cancel states:

The request cannot be canceled if it is currently being processed; in that case, it will be handled as if gai_cancel() has never been called.

The source also shows that gai_cancel just removes the request from the queue, so the behavior might be somewhat unexpected and should be documented appropriate (where?)

@ghostghost added the area-System.Net label Jan 15, 2021
@ghost

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

#34633 added async support for name resolution on glibc-based Unix-distros, this PR adds cancellation.

Note

The man-page of gai_cancel states:

The request cannot be canceled if it is currently being processed; in that case, it will be handled as if gai_cancel() has never been called.

The source also shows that gai_cancel just removes the request from the queue, so the behavior might be somewhat unexpected and should be documented appropriate.

Author:gfoidl
Assignees:-
Labels:

area-System.Net

Milestone:-

Task task = Dns.GetHostAddressesAsync(TestSettings.UncachedHost, cts.Token);
for (int i = 0; i < numberOfRequests; ++i)
{
Task task = Dns.GetHostAddressesAsync(TestSettings.UncachedHost, cts.Token);

@gfoidlgfoidlJan 15, 2021

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.

See #43816 (comment)
If this is considered reliable enough, so that issue is fixed with this change.

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.

I'll let @wfurt comment, but this seems like at some point it's going to fail spuriously in CI.

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 seems like the TestSettings.UncachedHost is already used twice and the second use could be cached - certainly in case of systemd resolver. If we want to improve chance of failure, I think each round should use unique name. And the test was already problematic in CI.

We could also accept the reality that cancellation is best-effort and timing sensitive and verify that if task failed, OperationCanceledException is only one reason.

We could also use SkipTestException. That would not change the test run much but we could at least see reports over time.

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.

So we could do this strategy:

  1. update the tests here to use SkipTestException, so it won't break CI but we still get some data for the cancellation-tests
  2. provide a proper / more robust solution when adressing Move name resolution cancellation test into Docker #43816

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.

62f05fe adds SkipTestException. OK as proposed in the comment before?

Comment threadsrc/libraries/Native/Unix/System.Native/pal_networking.c Outdated

@wfurtwfurt left a comment

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.

LGTM

@karelz

Copy link
Copy Markdown
Member

@stephentoub any additional concerns, or can we merge?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Besides the code we should have a look on how to document the somewhat unintuitive behavior of cancellation on unix -- see top post.

@stephentoub

Copy link
Copy Markdown
Member

we should have a look on how to document the somewhat unintuitive behavior of cancellation on unix

All attempts at cancellation are best effort, and there are many places where certain sections of execution aren't interruptible by cancellation. It's unfortunate that the support provided by glibc isn't better here, but I don't think we need to or even can get into the nitty gritty of exactly what's cancelable when. Hopefully in the future this can be improved.

@stephentoub

stephentoub commented Feb 3, 2021

Copy link
Copy Markdown
Member

I do have a more general question, though. Given the limitation, is it worth it? This change adds some complication and cost; will there generally be a payoff, or will we often be in the non-cancelable case?

try
{
await Task.WhenAll(tasks);
throw new SkipTestException("GetHostAddressesAsync should fail but it did not.");

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.

No one's going to notice this, especially in CI. Could we just keep retrying until it does fail? Folks will notice hangs ;-)

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.

Like a148365?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

will we often be in the non-cancelable case?

I don't have numbers for this, but my gut feeling tells that with current implemenation in glibc, where a request is just removed from the queue, a lot of operations aren't cancelable. Especially #43816 wouldn't work ("these tests might be moved into a Docker container with a non-working DNS server that will never respond") as this will just hang.

In e.g. server environment where the queue will be flooded with requests, it's more likeley to actually cancel (= remove from the queue) a request.

TBH I don't know if it is worth it, hope that you have an answer for this 😉

@wfurt

wfurt commented Feb 5, 2021

Copy link
Copy Markdown
Member

will we often be in the non-cancelable case?

I don't have numbers for this, but my gut feeling tells that with current implemenation in glibc, where a request is just removed from the queue, a lot of operations aren't cancelable. Especially #43816 wouldn't work ("these tests might be moved into a Docker container with a non-working DNS server that will never respond") as this will just hang.

In e.g. server environment where the queue will be flooded with requests, it's more likeley to actually cancel (= remove from the queue) a request.

TBH I don't know if it is worth it, hope that you have an answer for this 😉

To me, the value of cancelation is ability to fail lookup that takes too long - for whatever reason. That gives caller option to handle that any way they want. Whether we can actually cancel operation inside glibc is secondary IMHO. Since we register delegate, could we do that somehow?

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Since we register delegate, could we do that somehow?

gai_cancel returns either EAI_CANCELLED, EAI_NOTCANCELLED, or EAI_ALLDONE.
We could return this value to

Interop.Sys.CancelGetHostEntryForNameAsync(context->CancelHandle);
and then decide how to continue.

EAI_CANCELLED or EAI_ALLDONE are already handled by the current state of the PR.

EAI_NOTCANCELLED is the problematic case. We could return a canceled task the caller, but would need to keep the context alive in order to get no AV (I assume) if the native lookup completes anytime and invokes the callback

which is
privateunsafestructGetHostEntryForNameContext
{
publicInterop.Sys.HostEntryResult;
publicIntPtrState;
.

Right now I have no real idea on how to do this reliable, withou leaking memory or too much complication of the code.

@gfoidl

Copy link
Copy Markdown
MemberAuthor

Closing as per discussion in #48566

In short: getaddrinfo_a is a sub-optimal api, that doesn't perform real async name resolution. Other ways will be explored.

@gfoidlgfoidl closed this Feb 23, 2021
@gfoidl
gfoidl deleted the unix-async-name-resolution_cancellation branch February 23, 2021 20:27
@gfoidl
gfoidl restored the unix-async-name-resolution_cancellation branch March 4, 2021 08:29
@gfoidl
gfoidl deleted the unix-async-name-resolution_cancellation branch March 4, 2021 08:31
@ghostghost locked as resolved and limited conversation to collaborators Apr 3, 2021
@karelzkarelz added this to the 6.0.0 milestone May 20, 2021
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.

4 participants

@gfoidl@karelz@stephentoub@wfurt