Add Reverse Diagnostics Server - #33307

Merged
josalem merged 52 commits into
dotnet:masterfrom
josalem:dev/josalem/diag-server-handshake
Apr 20, 2020
Merged

Add Reverse Diagnostics Server#33307
josalem merged 52 commits into
dotnet:masterfrom
josalem:dev/josalem/diag-server-handshake

Conversation

@josalem

@josalemjosalem commented Mar 6, 2020

Copy link
Copy Markdown
Contributor

This PR adds the ability for the runtime to connect to a pre-existing IPC Transport for the Diagnostics Server. This enables several interesting scenarios, including:

  • Many apps connecting to a single diagnostics agent
  • tracing via IPC at startup (imagine doing dotnet trace run <executable> ...)
  • A busybox-esque agent being configurable in a side-car container
  • A host-based agent running and tracing an application in a container

This is achieved, by adding the non-blocking Accept (think listen on Linux), Connect, and Poll APIs to the diagnostics PAL. Using these, the runtime is able to listen on the original IPC Transport it creates ($TMPDIR/dotnet-diagnostics-<pid>) and this reversed connection if configured.

This reversed connection is opt-in and only activates when a path is specified in the DOTNET_DiagnosticsMonitorAddress environment variable.

The following logic is almost entirely inside DiagnosticsIpcFactory::GetNExtAvailableStream(...)

If a user configures this mechanism, the runtime will infinitely attempt to connect the specified transport and is resilient to that transport closing and reopening. The retry logic is as follows:

  • Reverse connection is not configured => infinitely block on server connection
  • Reverse connection is configured
    • Reverse connection is successful => cache connection, set timeout to max (30s)
    • Reverse connection is unsuccessful or closed => set timeout to minimum (250ms) and poll on other connections, multiply by falloff factor (2) for each attempt until max (30s)

The runtime caches reverse connections so that it is not constantly attaching to the reverse transport every time poll times out or the server connection is used. These cache entries get cleared when a connection is used or the connection is hung up.

This PR is currently missing The following will be a separate PR:

  • Semantics for blocking startup of the runtime
    • To enable collecting startup events, we would add a configurable blocking timeout to runtime startup
    • an environment variable will take a value of -1 (infinite), or 0 to n milliseconds
    • this value will be used to determine how long to block eemain before an EventPipe session is started.
    • the default will be 0 (no block)

CC - @tommcdon@shirhatti@noahfalk@sywhang

@josalemjosalem added this to the 5.0 milestone Mar 6, 2020
@josalem
josalem requested review from noahfalk and sywhangMarch 6, 2020 22:28
@josalemjosalem self-assigned this Mar 6, 2020
@Dotnet-GitSync-Bot

Copy link
Copy Markdown
Collaborator

I couldn't add an area label to this PR.

Checkout this page to find out which area owner to ping, or please add exactly one area label to help train me in the future.

@noahfalknoahfalk 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.

Added a few comments and questions. Holding off on a more detailed review in expectation that things are still changing : )

Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsserverprotocolhelper.h Outdated
@josalem
josalem marked this pull request as ready for review March 18, 2020 00:06
@josalem
josalem requested a review from noahfalkMarch 18, 2020 00:06
@josalemjosalem changed the title [Draft] Add Reverse Diagnostics Server (client-mode)Add Reverse Diagnostics Server (client-mode)Mar 18, 2020

@noahfalknoahfalk 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.

Its shaping up but will still need some more work to be robust. Happy to chat if you've got questions about anything.

Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated

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 would add an assert that that OVERLAPPED operation is complete. I would also test to confirm that DisconnectNamedPipe() finishes a ConnectNamedPipe operation when it is still pending. Destroying an OVERLAPPED struct before the operation ends usually causes painful to debug memory corruption issues.

Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
@josalem
josalemforce-pushed the dev/josalem/diag-server-handshake branch from 9f108d8 to 20f3745CompareApril 1, 2020 22:41

@noahfalknoahfalk 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.

Tests and functional correctness looking way better! I still have a few requests on the API design, performance, and additional tests but nothing as critical as the last iteration.

Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/vm/ipcstreamfactory.cpp Outdated
Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs
John Salem added 8 commits April 8, 2020 09:54
* Adds ConnectionState class for hiding server/client diff
* simplifies code for easier reading
* test was creating a pipe with a 0 buffer
* runtime needs to handle a 0 buffer namedpipe
* makes advertisement not block for more than 100 ms
* TODO: implement on non-windows
@josalem

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@josalem
josalem requested a review from noahfalkApril 17, 2020 22:18

@noahfalknoahfalk 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.

Alright, things are starting to look ship shape 👍 I did find a few more minor potential issues, comments inline.

Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h
Comment threadsrc/coreclr/src/vm/ipcstreamfactory.cpp
_pIpc->Close(callback);
if (_pStream != nullptr)
_pStream->Close(callback);
}

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.

_pIpc and _pStream need to be deleted (not that a leak on shutdown would really matter, but may as well clean up properly)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I specifically leaked these since the PAL is unaware of shutdown paths and has access to these pointers. This method is specifically called from a different thread than the server thread. If we delete them in this code path it can lead to AVs on the server thread in the PAL (inside IpcStream::DiagnosticsIpc::Poll specifically). Rather than introduce some form of knowledge of runtime state to the PAL or potentially adding locks protecting access I opted to just leak the memory on shutdown, since that is the only place this method is called. I should add a comment that calls out this assumption, though.

Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs Outdated
@josalem

Copy link
Copy Markdown
ContributorAuthor

Remaining failure appears to be an AzDO Package Feed or NuGet manifest error. All test runs passed.

@josalemjosalem changed the title Add Reverse Diagnostics Server (client-mode)Add Reverse Diagnostics ServerApr 20, 2020
@josalem
josalem merged commit 629dba5 into dotnet:masterApr 20, 2020
jkotas added a commit that referenced this pull request May 3, 2020
jkotas added a commit that referenced this pull request May 3, 2020
josalem pushed a commit to josalem/runtime that referenced this pull request May 7, 2020
@ghostghost locked as resolved and limited conversation to collaborators Dec 10, 2020
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

@josalem@Dotnet-GitSync-Bot@noahfalk@tommcdon
, '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

Add Reverse Diagnostics Server - #33307

Merged
josalem merged 52 commits into
dotnet:masterfrom
josalem:dev/josalem/diag-server-handshake
Apr 20, 2020
Merged

Add Reverse Diagnostics Server#33307
josalem merged 52 commits into
dotnet:masterfrom
josalem:dev/josalem/diag-server-handshake

Conversation

@josalem

@josalemjosalem commented Mar 6, 2020

Copy link
Copy Markdown
Contributor

This PR adds the ability for the runtime to connect to a pre-existing IPC Transport for the Diagnostics Server. This enables several interesting scenarios, including:

  • Many apps connecting to a single diagnostics agent
  • tracing via IPC at startup (imagine doing dotnet trace run <executable> ...)
  • A busybox-esque agent being configurable in a side-car container
  • A host-based agent running and tracing an application in a container

This is achieved, by adding the non-blocking Accept (think listen on Linux), Connect, and Poll APIs to the diagnostics PAL. Using these, the runtime is able to listen on the original IPC Transport it creates ($TMPDIR/dotnet-diagnostics-<pid>) and this reversed connection if configured.

This reversed connection is opt-in and only activates when a path is specified in the DOTNET_DiagnosticsMonitorAddress environment variable.

The following logic is almost entirely inside DiagnosticsIpcFactory::GetNExtAvailableStream(...)

If a user configures this mechanism, the runtime will infinitely attempt to connect the specified transport and is resilient to that transport closing and reopening. The retry logic is as follows:

  • Reverse connection is not configured => infinitely block on server connection
  • Reverse connection is configured
    • Reverse connection is successful => cache connection, set timeout to max (30s)
    • Reverse connection is unsuccessful or closed => set timeout to minimum (250ms) and poll on other connections, multiply by falloff factor (2) for each attempt until max (30s)

The runtime caches reverse connections so that it is not constantly attaching to the reverse transport every time poll times out or the server connection is used. These cache entries get cleared when a connection is used or the connection is hung up.

This PR is currently missing The following will be a separate PR:

  • Semantics for blocking startup of the runtime
    • To enable collecting startup events, we would add a configurable blocking timeout to runtime startup
    • an environment variable will take a value of -1 (infinite), or 0 to n milliseconds
    • this value will be used to determine how long to block eemain before an EventPipe session is started.
    • the default will be 0 (no block)

CC - @tommcdon@shirhatti@noahfalk@sywhang

@josalemjosalem added this to the 5.0 milestone Mar 6, 2020
@josalem
josalem requested review from noahfalk and sywhangMarch 6, 2020 22:28
@josalemjosalem self-assigned this Mar 6, 2020
@Dotnet-GitSync-Bot

Copy link
Copy Markdown
Collaborator

I couldn't add an area label to this PR.

Checkout this page to find out which area owner to ping, or please add exactly one area label to help train me in the future.

@noahfalknoahfalk 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.

Added a few comments and questions. Holding off on a more detailed review in expectation that things are still changing : )

Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsserverprotocolhelper.h Outdated
@josalem
josalem marked this pull request as ready for review March 18, 2020 00:06
@josalem
josalem requested a review from noahfalkMarch 18, 2020 00:06
@josalemjosalem changed the title [Draft] Add Reverse Diagnostics Server (client-mode)Add Reverse Diagnostics Server (client-mode)Mar 18, 2020

@noahfalknoahfalk 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.

Its shaping up but will still need some more work to be robust. Happy to chat if you've got questions about anything.

Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated

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 would add an assert that that OVERLAPPED operation is complete. I would also test to confirm that DisconnectNamedPipe() finishes a ConnectNamedPipe operation when it is still pending. Destroying an OVERLAPPED struct before the operation ends usually causes painful to debug memory corruption issues.

Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
@josalem
josalemforce-pushed the dev/josalem/diag-server-handshake branch from 9f108d8 to 20f3745CompareApril 1, 2020 22:41

@noahfalknoahfalk 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.

Tests and functional correctness looking way better! I still have a few requests on the API design, performance, and additional tests but nothing as critical as the last iteration.

Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/vm/ipcstreamfactory.cpp Outdated
Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs
John Salem added 8 commits April 8, 2020 09:54
* Adds ConnectionState class for hiding server/client diff
* simplifies code for easier reading
* test was creating a pipe with a 0 buffer
* runtime needs to handle a 0 buffer namedpipe
* makes advertisement not block for more than 100 ms
* TODO: implement on non-windows
@josalem

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@josalem
josalem requested a review from noahfalkApril 17, 2020 22:18

@noahfalknoahfalk 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.

Alright, things are starting to look ship shape 👍 I did find a few more minor potential issues, comments inline.

Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h
Comment threadsrc/coreclr/src/vm/ipcstreamfactory.cpp
_pIpc->Close(callback);
if (_pStream != nullptr)
_pStream->Close(callback);
}

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.

_pIpc and _pStream need to be deleted (not that a leak on shutdown would really matter, but may as well clean up properly)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I specifically leaked these since the PAL is unaware of shutdown paths and has access to these pointers. This method is specifically called from a different thread than the server thread. If we delete them in this code path it can lead to AVs on the server thread in the PAL (inside IpcStream::DiagnosticsIpc::Poll specifically). Rather than introduce some form of knowledge of runtime state to the PAL or potentially adding locks protecting access I opted to just leak the memory on shutdown, since that is the only place this method is called. I should add a comment that calls out this assumption, though.

Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs Outdated
@josalem

Copy link
Copy Markdown
ContributorAuthor

Remaining failure appears to be an AzDO Package Feed or NuGet manifest error. All test runs passed.

@josalemjosalem changed the title Add Reverse Diagnostics Server (client-mode)Add Reverse Diagnostics ServerApr 20, 2020
@josalem
josalem merged commit 629dba5 into dotnet:masterApr 20, 2020
jkotas added a commit that referenced this pull request May 3, 2020
jkotas added a commit that referenced this pull request May 3, 2020
josalem pushed a commit to josalem/runtime that referenced this pull request May 7, 2020
@ghostghost locked as resolved and limited conversation to collaborators Dec 10, 2020
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

@josalem@Dotnet-GitSync-Bot@noahfalk@tommcdon
, '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

Add Reverse Diagnostics Server - #33307

Merged
josalem merged 52 commits into
dotnet:masterfrom
josalem:dev/josalem/diag-server-handshake
Apr 20, 2020
Merged

Add Reverse Diagnostics Server#33307
josalem merged 52 commits into
dotnet:masterfrom
josalem:dev/josalem/diag-server-handshake

Conversation

@josalem

@josalemjosalem commented Mar 6, 2020

Copy link
Copy Markdown
Contributor

This PR adds the ability for the runtime to connect to a pre-existing IPC Transport for the Diagnostics Server. This enables several interesting scenarios, including:

  • Many apps connecting to a single diagnostics agent
  • tracing via IPC at startup (imagine doing dotnet trace run <executable> ...)
  • A busybox-esque agent being configurable in a side-car container
  • A host-based agent running and tracing an application in a container

This is achieved, by adding the non-blocking Accept (think listen on Linux), Connect, and Poll APIs to the diagnostics PAL. Using these, the runtime is able to listen on the original IPC Transport it creates ($TMPDIR/dotnet-diagnostics-<pid>) and this reversed connection if configured.

This reversed connection is opt-in and only activates when a path is specified in the DOTNET_DiagnosticsMonitorAddress environment variable.

The following logic is almost entirely inside DiagnosticsIpcFactory::GetNExtAvailableStream(...)

If a user configures this mechanism, the runtime will infinitely attempt to connect the specified transport and is resilient to that transport closing and reopening. The retry logic is as follows:

  • Reverse connection is not configured => infinitely block on server connection
  • Reverse connection is configured
    • Reverse connection is successful => cache connection, set timeout to max (30s)
    • Reverse connection is unsuccessful or closed => set timeout to minimum (250ms) and poll on other connections, multiply by falloff factor (2) for each attempt until max (30s)

The runtime caches reverse connections so that it is not constantly attaching to the reverse transport every time poll times out or the server connection is used. These cache entries get cleared when a connection is used or the connection is hung up.

This PR is currently missing The following will be a separate PR:

  • Semantics for blocking startup of the runtime
    • To enable collecting startup events, we would add a configurable blocking timeout to runtime startup
    • an environment variable will take a value of -1 (infinite), or 0 to n milliseconds
    • this value will be used to determine how long to block eemain before an EventPipe session is started.
    • the default will be 0 (no block)

CC - @tommcdon@shirhatti@noahfalk@sywhang

@josalemjosalem added this to the 5.0 milestone Mar 6, 2020
@josalem
josalem requested review from noahfalk and sywhangMarch 6, 2020 22:28
@josalemjosalem self-assigned this Mar 6, 2020
@Dotnet-GitSync-Bot

Copy link
Copy Markdown
Collaborator

I couldn't add an area label to this PR.

Checkout this page to find out which area owner to ping, or please add exactly one area label to help train me in the future.

@noahfalknoahfalk 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.

Added a few comments and questions. Holding off on a more detailed review in expectation that things are still changing : )

Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsserverprotocolhelper.h Outdated
@josalem
josalem marked this pull request as ready for review March 18, 2020 00:06
@josalem
josalem requested a review from noahfalkMarch 18, 2020 00:06
@josalemjosalem changed the title [Draft] Add Reverse Diagnostics Server (client-mode)Add Reverse Diagnostics Server (client-mode)Mar 18, 2020

@noahfalknoahfalk 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.

Its shaping up but will still need some more work to be robust. Happy to chat if you've got questions about anything.

Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated

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 would add an assert that that OVERLAPPED operation is complete. I would also test to confirm that DisconnectNamedPipe() finishes a ConnectNamedPipe operation when it is still pending. Destroying an OVERLAPPED struct before the operation ends usually causes painful to debug memory corruption issues.

Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
@josalem
josalemforce-pushed the dev/josalem/diag-server-handshake branch from 9f108d8 to 20f3745CompareApril 1, 2020 22:41

@noahfalknoahfalk 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.

Tests and functional correctness looking way better! I still have a few requests on the API design, performance, and additional tests but nothing as critical as the last iteration.

Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/vm/ipcstreamfactory.cpp Outdated
Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs
John Salem added 8 commits April 8, 2020 09:54
* Adds ConnectionState class for hiding server/client diff
* simplifies code for easier reading
* test was creating a pipe with a 0 buffer
* runtime needs to handle a 0 buffer namedpipe
* makes advertisement not block for more than 100 ms
* TODO: implement on non-windows
@josalem

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@josalem
josalem requested a review from noahfalkApril 17, 2020 22:18

@noahfalknoahfalk 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.

Alright, things are starting to look ship shape 👍 I did find a few more minor potential issues, comments inline.

Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h
Comment threadsrc/coreclr/src/vm/ipcstreamfactory.cpp
_pIpc->Close(callback);
if (_pStream != nullptr)
_pStream->Close(callback);
}

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.

_pIpc and _pStream need to be deleted (not that a leak on shutdown would really matter, but may as well clean up properly)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I specifically leaked these since the PAL is unaware of shutdown paths and has access to these pointers. This method is specifically called from a different thread than the server thread. If we delete them in this code path it can lead to AVs on the server thread in the PAL (inside IpcStream::DiagnosticsIpc::Poll specifically). Rather than introduce some form of knowledge of runtime state to the PAL or potentially adding locks protecting access I opted to just leak the memory on shutdown, since that is the only place this method is called. I should add a comment that calls out this assumption, though.

Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs Outdated
@josalem

Copy link
Copy Markdown
ContributorAuthor

Remaining failure appears to be an AzDO Package Feed or NuGet manifest error. All test runs passed.

@josalemjosalem changed the title Add Reverse Diagnostics Server (client-mode)Add Reverse Diagnostics ServerApr 20, 2020
@josalem
josalem merged commit 629dba5 into dotnet:masterApr 20, 2020
jkotas added a commit that referenced this pull request May 3, 2020
jkotas added a commit that referenced this pull request May 3, 2020
josalem pushed a commit to josalem/runtime that referenced this pull request May 7, 2020
@ghostghost locked as resolved and limited conversation to collaborators Dec 10, 2020
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

@josalem@Dotnet-GitSync-Bot@noahfalk@tommcdon
, '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

Add Reverse Diagnostics Server - #33307

Merged
josalem merged 52 commits into
dotnet:masterfrom
josalem:dev/josalem/diag-server-handshake
Apr 20, 2020
Merged

Add Reverse Diagnostics Server#33307
josalem merged 52 commits into
dotnet:masterfrom
josalem:dev/josalem/diag-server-handshake

Conversation

@josalem

@josalemjosalem commented Mar 6, 2020

Copy link
Copy Markdown
Contributor

This PR adds the ability for the runtime to connect to a pre-existing IPC Transport for the Diagnostics Server. This enables several interesting scenarios, including:

  • Many apps connecting to a single diagnostics agent
  • tracing via IPC at startup (imagine doing dotnet trace run <executable> ...)
  • A busybox-esque agent being configurable in a side-car container
  • A host-based agent running and tracing an application in a container

This is achieved, by adding the non-blocking Accept (think listen on Linux), Connect, and Poll APIs to the diagnostics PAL. Using these, the runtime is able to listen on the original IPC Transport it creates ($TMPDIR/dotnet-diagnostics-<pid>) and this reversed connection if configured.

This reversed connection is opt-in and only activates when a path is specified in the DOTNET_DiagnosticsMonitorAddress environment variable.

The following logic is almost entirely inside DiagnosticsIpcFactory::GetNExtAvailableStream(...)

If a user configures this mechanism, the runtime will infinitely attempt to connect the specified transport and is resilient to that transport closing and reopening. The retry logic is as follows:

  • Reverse connection is not configured => infinitely block on server connection
  • Reverse connection is configured
    • Reverse connection is successful => cache connection, set timeout to max (30s)
    • Reverse connection is unsuccessful or closed => set timeout to minimum (250ms) and poll on other connections, multiply by falloff factor (2) for each attempt until max (30s)

The runtime caches reverse connections so that it is not constantly attaching to the reverse transport every time poll times out or the server connection is used. These cache entries get cleared when a connection is used or the connection is hung up.

This PR is currently missing The following will be a separate PR:

  • Semantics for blocking startup of the runtime
    • To enable collecting startup events, we would add a configurable blocking timeout to runtime startup
    • an environment variable will take a value of -1 (infinite), or 0 to n milliseconds
    • this value will be used to determine how long to block eemain before an EventPipe session is started.
    • the default will be 0 (no block)

CC - @tommcdon@shirhatti@noahfalk@sywhang

@josalemjosalem added this to the 5.0 milestone Mar 6, 2020
@josalem
josalem requested review from noahfalk and sywhangMarch 6, 2020 22:28
@josalemjosalem self-assigned this Mar 6, 2020
@Dotnet-GitSync-Bot

Copy link
Copy Markdown
Collaborator

I couldn't add an area label to this PR.

Checkout this page to find out which area owner to ping, or please add exactly one area label to help train me in the future.

@noahfalknoahfalk 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.

Added a few comments and questions. Holding off on a more detailed review in expectation that things are still changing : )

Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsserverprotocolhelper.h Outdated
@josalem
josalem marked this pull request as ready for review March 18, 2020 00:06
@josalem
josalem requested a review from noahfalkMarch 18, 2020 00:06
@josalemjosalem changed the title [Draft] Add Reverse Diagnostics Server (client-mode)Add Reverse Diagnostics Server (client-mode)Mar 18, 2020

@noahfalknoahfalk 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.

Its shaping up but will still need some more work to be robust. Happy to chat if you've got questions about anything.

Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated

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 would add an assert that that OVERLAPPED operation is complete. I would also test to confirm that DisconnectNamedPipe() finishes a ConnectNamedPipe operation when it is still pending. Destroying an OVERLAPPED struct before the operation ends usually causes painful to debug memory corruption issues.

Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
@josalem
josalemforce-pushed the dev/josalem/diag-server-handshake branch from 9f108d8 to 20f3745CompareApril 1, 2020 22:41

@noahfalknoahfalk 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.

Tests and functional correctness looking way better! I still have a few requests on the API design, performance, and additional tests but nothing as critical as the last iteration.

Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/vm/ipcstreamfactory.cpp Outdated
Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs
John Salem added 8 commits April 8, 2020 09:54
* Adds ConnectionState class for hiding server/client diff
* simplifies code for easier reading
* test was creating a pipe with a 0 buffer
* runtime needs to handle a 0 buffer namedpipe
* makes advertisement not block for more than 100 ms
* TODO: implement on non-windows
@josalem

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@josalem
josalem requested a review from noahfalkApril 17, 2020 22:18

@noahfalknoahfalk 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.

Alright, things are starting to look ship shape 👍 I did find a few more minor potential issues, comments inline.

Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h
Comment threadsrc/coreclr/src/vm/ipcstreamfactory.cpp
_pIpc->Close(callback);
if (_pStream != nullptr)
_pStream->Close(callback);
}

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.

_pIpc and _pStream need to be deleted (not that a leak on shutdown would really matter, but may as well clean up properly)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I specifically leaked these since the PAL is unaware of shutdown paths and has access to these pointers. This method is specifically called from a different thread than the server thread. If we delete them in this code path it can lead to AVs on the server thread in the PAL (inside IpcStream::DiagnosticsIpc::Poll specifically). Rather than introduce some form of knowledge of runtime state to the PAL or potentially adding locks protecting access I opted to just leak the memory on shutdown, since that is the only place this method is called. I should add a comment that calls out this assumption, though.

Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs Outdated
@josalem

Copy link
Copy Markdown
ContributorAuthor

Remaining failure appears to be an AzDO Package Feed or NuGet manifest error. All test runs passed.

@josalemjosalem changed the title Add Reverse Diagnostics Server (client-mode)Add Reverse Diagnostics ServerApr 20, 2020
@josalem
josalem merged commit 629dba5 into dotnet:masterApr 20, 2020
jkotas added a commit that referenced this pull request May 3, 2020
jkotas added a commit that referenced this pull request May 3, 2020
josalem pushed a commit to josalem/runtime that referenced this pull request May 7, 2020
@ghostghost locked as resolved and limited conversation to collaborators Dec 10, 2020
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

@josalem@Dotnet-GitSync-Bot@noahfalk@tommcdon
, '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

Add Reverse Diagnostics Server - #33307

Merged
josalem merged 52 commits into
dotnet:masterfrom
josalem:dev/josalem/diag-server-handshake
Apr 20, 2020
Merged

Add Reverse Diagnostics Server#33307
josalem merged 52 commits into
dotnet:masterfrom
josalem:dev/josalem/diag-server-handshake

Conversation

@josalem

@josalemjosalem commented Mar 6, 2020

Copy link
Copy Markdown
Contributor

This PR adds the ability for the runtime to connect to a pre-existing IPC Transport for the Diagnostics Server. This enables several interesting scenarios, including:

  • Many apps connecting to a single diagnostics agent
  • tracing via IPC at startup (imagine doing dotnet trace run <executable> ...)
  • A busybox-esque agent being configurable in a side-car container
  • A host-based agent running and tracing an application in a container

This is achieved, by adding the non-blocking Accept (think listen on Linux), Connect, and Poll APIs to the diagnostics PAL. Using these, the runtime is able to listen on the original IPC Transport it creates ($TMPDIR/dotnet-diagnostics-<pid>) and this reversed connection if configured.

This reversed connection is opt-in and only activates when a path is specified in the DOTNET_DiagnosticsMonitorAddress environment variable.

The following logic is almost entirely inside DiagnosticsIpcFactory::GetNExtAvailableStream(...)

If a user configures this mechanism, the runtime will infinitely attempt to connect the specified transport and is resilient to that transport closing and reopening. The retry logic is as follows:

  • Reverse connection is not configured => infinitely block on server connection
  • Reverse connection is configured
    • Reverse connection is successful => cache connection, set timeout to max (30s)
    • Reverse connection is unsuccessful or closed => set timeout to minimum (250ms) and poll on other connections, multiply by falloff factor (2) for each attempt until max (30s)

The runtime caches reverse connections so that it is not constantly attaching to the reverse transport every time poll times out or the server connection is used. These cache entries get cleared when a connection is used or the connection is hung up.

This PR is currently missing The following will be a separate PR:

  • Semantics for blocking startup of the runtime
    • To enable collecting startup events, we would add a configurable blocking timeout to runtime startup
    • an environment variable will take a value of -1 (infinite), or 0 to n milliseconds
    • this value will be used to determine how long to block eemain before an EventPipe session is started.
    • the default will be 0 (no block)

CC - @tommcdon@shirhatti@noahfalk@sywhang

@josalemjosalem added this to the 5.0 milestone Mar 6, 2020
@josalem
josalem requested review from noahfalk and sywhangMarch 6, 2020 22:28
@josalemjosalem self-assigned this Mar 6, 2020
@Dotnet-GitSync-Bot

Copy link
Copy Markdown
Collaborator

I couldn't add an area label to this PR.

Checkout this page to find out which area owner to ping, or please add exactly one area label to help train me in the future.

@noahfalknoahfalk 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.

Added a few comments and questions. Holding off on a more detailed review in expectation that things are still changing : )

Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsserverprotocolhelper.h Outdated
@josalem
josalem marked this pull request as ready for review March 18, 2020 00:06
@josalem
josalem requested a review from noahfalkMarch 18, 2020 00:06
@josalemjosalem changed the title [Draft] Add Reverse Diagnostics Server (client-mode)Add Reverse Diagnostics Server (client-mode)Mar 18, 2020

@noahfalknoahfalk 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.

Its shaping up but will still need some more work to be robust. Happy to chat if you've got questions about anything.

Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated

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 would add an assert that that OVERLAPPED operation is complete. I would also test to confirm that DisconnectNamedPipe() finishes a ConnectNamedPipe operation when it is still pending. Destroying an OVERLAPPED struct before the operation ends usually causes painful to debug memory corruption issues.

Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
@josalem
josalemforce-pushed the dev/josalem/diag-server-handshake branch from 9f108d8 to 20f3745CompareApril 1, 2020 22:41

@noahfalknoahfalk 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.

Tests and functional correctness looking way better! I still have a few requests on the API design, performance, and additional tests but nothing as critical as the last iteration.

Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/vm/ipcstreamfactory.cpp Outdated
Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs
John Salem added 8 commits April 8, 2020 09:54
* Adds ConnectionState class for hiding server/client diff
* simplifies code for easier reading
* test was creating a pipe with a 0 buffer
* runtime needs to handle a 0 buffer namedpipe
* makes advertisement not block for more than 100 ms
* TODO: implement on non-windows
@josalem

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@josalem
josalem requested a review from noahfalkApril 17, 2020 22:18

@noahfalknoahfalk 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.

Alright, things are starting to look ship shape 👍 I did find a few more minor potential issues, comments inline.

Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h
Comment threadsrc/coreclr/src/vm/ipcstreamfactory.cpp
_pIpc->Close(callback);
if (_pStream != nullptr)
_pStream->Close(callback);
}

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.

_pIpc and _pStream need to be deleted (not that a leak on shutdown would really matter, but may as well clean up properly)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I specifically leaked these since the PAL is unaware of shutdown paths and has access to these pointers. This method is specifically called from a different thread than the server thread. If we delete them in this code path it can lead to AVs on the server thread in the PAL (inside IpcStream::DiagnosticsIpc::Poll specifically). Rather than introduce some form of knowledge of runtime state to the PAL or potentially adding locks protecting access I opted to just leak the memory on shutdown, since that is the only place this method is called. I should add a comment that calls out this assumption, though.

Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs Outdated
@josalem

Copy link
Copy Markdown
ContributorAuthor

Remaining failure appears to be an AzDO Package Feed or NuGet manifest error. All test runs passed.

@josalemjosalem changed the title Add Reverse Diagnostics Server (client-mode)Add Reverse Diagnostics ServerApr 20, 2020
@josalem
josalem merged commit 629dba5 into dotnet:masterApr 20, 2020
jkotas added a commit that referenced this pull request May 3, 2020
jkotas added a commit that referenced this pull request May 3, 2020
josalem pushed a commit to josalem/runtime that referenced this pull request May 7, 2020
@ghostghost locked as resolved and limited conversation to collaborators Dec 10, 2020
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

@josalem@Dotnet-GitSync-Bot@noahfalk@tommcdon
, '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

Add Reverse Diagnostics Server - #33307

Merged
josalem merged 52 commits into
dotnet:masterfrom
josalem:dev/josalem/diag-server-handshake
Apr 20, 2020
Merged

Add Reverse Diagnostics Server#33307
josalem merged 52 commits into
dotnet:masterfrom
josalem:dev/josalem/diag-server-handshake

Conversation

@josalem

@josalemjosalem commented Mar 6, 2020

Copy link
Copy Markdown
Contributor

This PR adds the ability for the runtime to connect to a pre-existing IPC Transport for the Diagnostics Server. This enables several interesting scenarios, including:

  • Many apps connecting to a single diagnostics agent
  • tracing via IPC at startup (imagine doing dotnet trace run <executable> ...)
  • A busybox-esque agent being configurable in a side-car container
  • A host-based agent running and tracing an application in a container

This is achieved, by adding the non-blocking Accept (think listen on Linux), Connect, and Poll APIs to the diagnostics PAL. Using these, the runtime is able to listen on the original IPC Transport it creates ($TMPDIR/dotnet-diagnostics-<pid>) and this reversed connection if configured.

This reversed connection is opt-in and only activates when a path is specified in the DOTNET_DiagnosticsMonitorAddress environment variable.

The following logic is almost entirely inside DiagnosticsIpcFactory::GetNExtAvailableStream(...)

If a user configures this mechanism, the runtime will infinitely attempt to connect the specified transport and is resilient to that transport closing and reopening. The retry logic is as follows:

  • Reverse connection is not configured => infinitely block on server connection
  • Reverse connection is configured
    • Reverse connection is successful => cache connection, set timeout to max (30s)
    • Reverse connection is unsuccessful or closed => set timeout to minimum (250ms) and poll on other connections, multiply by falloff factor (2) for each attempt until max (30s)

The runtime caches reverse connections so that it is not constantly attaching to the reverse transport every time poll times out or the server connection is used. These cache entries get cleared when a connection is used or the connection is hung up.

This PR is currently missing The following will be a separate PR:

  • Semantics for blocking startup of the runtime
    • To enable collecting startup events, we would add a configurable blocking timeout to runtime startup
    • an environment variable will take a value of -1 (infinite), or 0 to n milliseconds
    • this value will be used to determine how long to block eemain before an EventPipe session is started.
    • the default will be 0 (no block)

CC - @tommcdon@shirhatti@noahfalk@sywhang

@josalemjosalem added this to the 5.0 milestone Mar 6, 2020
@josalem
josalem requested review from noahfalk and sywhangMarch 6, 2020 22:28
@josalemjosalem self-assigned this Mar 6, 2020
@Dotnet-GitSync-Bot

Copy link
Copy Markdown
Collaborator

I couldn't add an area label to this PR.

Checkout this page to find out which area owner to ping, or please add exactly one area label to help train me in the future.

@noahfalknoahfalk 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.

Added a few comments and questions. Holding off on a more detailed review in expectation that things are still changing : )

Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsserverprotocolhelper.h Outdated
@josalem
josalem marked this pull request as ready for review March 18, 2020 00:06
@josalem
josalem requested a review from noahfalkMarch 18, 2020 00:06
@josalemjosalem changed the title [Draft] Add Reverse Diagnostics Server (client-mode)Add Reverse Diagnostics Server (client-mode)Mar 18, 2020

@noahfalknoahfalk 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.

Its shaping up but will still need some more work to be robust. Happy to chat if you've got questions about anything.

Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated

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 would add an assert that that OVERLAPPED operation is complete. I would also test to confirm that DisconnectNamedPipe() finishes a ConnectNamedPipe operation when it is still pending. Destroying an OVERLAPPED struct before the operation ends usually causes painful to debug memory corruption issues.

Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
@josalem
josalemforce-pushed the dev/josalem/diag-server-handshake branch from 9f108d8 to 20f3745CompareApril 1, 2020 22:41

@noahfalknoahfalk 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.

Tests and functional correctness looking way better! I still have a few requests on the API design, performance, and additional tests but nothing as critical as the last iteration.

Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/vm/ipcstreamfactory.cpp Outdated
Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs
John Salem added 8 commits April 8, 2020 09:54
* Adds ConnectionState class for hiding server/client diff
* simplifies code for easier reading
* test was creating a pipe with a 0 buffer
* runtime needs to handle a 0 buffer namedpipe
* makes advertisement not block for more than 100 ms
* TODO: implement on non-windows
@josalem

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@josalem
josalem requested a review from noahfalkApril 17, 2020 22:18

@noahfalknoahfalk 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.

Alright, things are starting to look ship shape 👍 I did find a few more minor potential issues, comments inline.

Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h
Comment threadsrc/coreclr/src/vm/ipcstreamfactory.cpp
_pIpc->Close(callback);
if (_pStream != nullptr)
_pStream->Close(callback);
}

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.

_pIpc and _pStream need to be deleted (not that a leak on shutdown would really matter, but may as well clean up properly)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I specifically leaked these since the PAL is unaware of shutdown paths and has access to these pointers. This method is specifically called from a different thread than the server thread. If we delete them in this code path it can lead to AVs on the server thread in the PAL (inside IpcStream::DiagnosticsIpc::Poll specifically). Rather than introduce some form of knowledge of runtime state to the PAL or potentially adding locks protecting access I opted to just leak the memory on shutdown, since that is the only place this method is called. I should add a comment that calls out this assumption, though.

Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs Outdated
@josalem

Copy link
Copy Markdown
ContributorAuthor

Remaining failure appears to be an AzDO Package Feed or NuGet manifest error. All test runs passed.

@josalemjosalem changed the title Add Reverse Diagnostics Server (client-mode)Add Reverse Diagnostics ServerApr 20, 2020
@josalem
josalem merged commit 629dba5 into dotnet:masterApr 20, 2020
jkotas added a commit that referenced this pull request May 3, 2020
jkotas added a commit that referenced this pull request May 3, 2020
josalem pushed a commit to josalem/runtime that referenced this pull request May 7, 2020
@ghostghost locked as resolved and limited conversation to collaborators Dec 10, 2020
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

@josalem@Dotnet-GitSync-Bot@noahfalk@tommcdon
, '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

Add Reverse Diagnostics Server - #33307

Merged
josalem merged 52 commits into
dotnet:masterfrom
josalem:dev/josalem/diag-server-handshake
Apr 20, 2020
Merged

Add Reverse Diagnostics Server#33307
josalem merged 52 commits into
dotnet:masterfrom
josalem:dev/josalem/diag-server-handshake

Conversation

@josalem

@josalemjosalem commented Mar 6, 2020

Copy link
Copy Markdown
Contributor

This PR adds the ability for the runtime to connect to a pre-existing IPC Transport for the Diagnostics Server. This enables several interesting scenarios, including:

  • Many apps connecting to a single diagnostics agent
  • tracing via IPC at startup (imagine doing dotnet trace run <executable> ...)
  • A busybox-esque agent being configurable in a side-car container
  • A host-based agent running and tracing an application in a container

This is achieved, by adding the non-blocking Accept (think listen on Linux), Connect, and Poll APIs to the diagnostics PAL. Using these, the runtime is able to listen on the original IPC Transport it creates ($TMPDIR/dotnet-diagnostics-<pid>) and this reversed connection if configured.

This reversed connection is opt-in and only activates when a path is specified in the DOTNET_DiagnosticsMonitorAddress environment variable.

The following logic is almost entirely inside DiagnosticsIpcFactory::GetNExtAvailableStream(...)

If a user configures this mechanism, the runtime will infinitely attempt to connect the specified transport and is resilient to that transport closing and reopening. The retry logic is as follows:

  • Reverse connection is not configured => infinitely block on server connection
  • Reverse connection is configured
    • Reverse connection is successful => cache connection, set timeout to max (30s)
    • Reverse connection is unsuccessful or closed => set timeout to minimum (250ms) and poll on other connections, multiply by falloff factor (2) for each attempt until max (30s)

The runtime caches reverse connections so that it is not constantly attaching to the reverse transport every time poll times out or the server connection is used. These cache entries get cleared when a connection is used or the connection is hung up.

This PR is currently missing The following will be a separate PR:

  • Semantics for blocking startup of the runtime
    • To enable collecting startup events, we would add a configurable blocking timeout to runtime startup
    • an environment variable will take a value of -1 (infinite), or 0 to n milliseconds
    • this value will be used to determine how long to block eemain before an EventPipe session is started.
    • the default will be 0 (no block)

CC - @tommcdon@shirhatti@noahfalk@sywhang

@josalemjosalem added this to the 5.0 milestone Mar 6, 2020
@josalem
josalem requested review from noahfalk and sywhangMarch 6, 2020 22:28
@josalemjosalem self-assigned this Mar 6, 2020
@Dotnet-GitSync-Bot

Copy link
Copy Markdown
Collaborator

I couldn't add an area label to this PR.

Checkout this page to find out which area owner to ping, or please add exactly one area label to help train me in the future.

@noahfalknoahfalk 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.

Added a few comments and questions. Holding off on a more detailed review in expectation that things are still changing : )

Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsserverprotocolhelper.h Outdated
@josalem
josalem marked this pull request as ready for review March 18, 2020 00:06
@josalem
josalem requested a review from noahfalkMarch 18, 2020 00:06
@josalemjosalem changed the title [Draft] Add Reverse Diagnostics Server (client-mode)Add Reverse Diagnostics Server (client-mode)Mar 18, 2020

@noahfalknoahfalk 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.

Its shaping up but will still need some more work to be robust. Happy to chat if you've got questions about anything.

Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated

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 would add an assert that that OVERLAPPED operation is complete. I would also test to confirm that DisconnectNamedPipe() finishes a ConnectNamedPipe operation when it is still pending. Destroying an OVERLAPPED struct before the operation ends usually causes painful to debug memory corruption issues.

Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
@josalem
josalemforce-pushed the dev/josalem/diag-server-handshake branch from 9f108d8 to 20f3745CompareApril 1, 2020 22:41

@noahfalknoahfalk 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.

Tests and functional correctness looking way better! I still have a few requests on the API design, performance, and additional tests but nothing as critical as the last iteration.

Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/vm/ipcstreamfactory.cpp Outdated
Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs
John Salem added 8 commits April 8, 2020 09:54
* Adds ConnectionState class for hiding server/client diff
* simplifies code for easier reading
* test was creating a pipe with a 0 buffer
* runtime needs to handle a 0 buffer namedpipe
* makes advertisement not block for more than 100 ms
* TODO: implement on non-windows
@josalem

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@josalem
josalem requested a review from noahfalkApril 17, 2020 22:18

@noahfalknoahfalk 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.

Alright, things are starting to look ship shape 👍 I did find a few more minor potential issues, comments inline.

Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h
Comment threadsrc/coreclr/src/vm/ipcstreamfactory.cpp
_pIpc->Close(callback);
if (_pStream != nullptr)
_pStream->Close(callback);
}

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.

_pIpc and _pStream need to be deleted (not that a leak on shutdown would really matter, but may as well clean up properly)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I specifically leaked these since the PAL is unaware of shutdown paths and has access to these pointers. This method is specifically called from a different thread than the server thread. If we delete them in this code path it can lead to AVs on the server thread in the PAL (inside IpcStream::DiagnosticsIpc::Poll specifically). Rather than introduce some form of knowledge of runtime state to the PAL or potentially adding locks protecting access I opted to just leak the memory on shutdown, since that is the only place this method is called. I should add a comment that calls out this assumption, though.

Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs Outdated
@josalem

Copy link
Copy Markdown
ContributorAuthor

Remaining failure appears to be an AzDO Package Feed or NuGet manifest error. All test runs passed.

@josalemjosalem changed the title Add Reverse Diagnostics Server (client-mode)Add Reverse Diagnostics ServerApr 20, 2020
@josalem
josalem merged commit 629dba5 into dotnet:masterApr 20, 2020
jkotas added a commit that referenced this pull request May 3, 2020
jkotas added a commit that referenced this pull request May 3, 2020
josalem pushed a commit to josalem/runtime that referenced this pull request May 7, 2020
@ghostghost locked as resolved and limited conversation to collaborators Dec 10, 2020
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

@josalem@Dotnet-GitSync-Bot@noahfalk@tommcdon
, '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

Add Reverse Diagnostics Server - #33307

Merged
josalem merged 52 commits into
dotnet:masterfrom
josalem:dev/josalem/diag-server-handshake
Apr 20, 2020
Merged

Add Reverse Diagnostics Server#33307
josalem merged 52 commits into
dotnet:masterfrom
josalem:dev/josalem/diag-server-handshake

Conversation

@josalem

@josalemjosalem commented Mar 6, 2020

Copy link
Copy Markdown
Contributor

This PR adds the ability for the runtime to connect to a pre-existing IPC Transport for the Diagnostics Server. This enables several interesting scenarios, including:

  • Many apps connecting to a single diagnostics agent
  • tracing via IPC at startup (imagine doing dotnet trace run <executable> ...)
  • A busybox-esque agent being configurable in a side-car container
  • A host-based agent running and tracing an application in a container

This is achieved, by adding the non-blocking Accept (think listen on Linux), Connect, and Poll APIs to the diagnostics PAL. Using these, the runtime is able to listen on the original IPC Transport it creates ($TMPDIR/dotnet-diagnostics-<pid>) and this reversed connection if configured.

This reversed connection is opt-in and only activates when a path is specified in the DOTNET_DiagnosticsMonitorAddress environment variable.

The following logic is almost entirely inside DiagnosticsIpcFactory::GetNExtAvailableStream(...)

If a user configures this mechanism, the runtime will infinitely attempt to connect the specified transport and is resilient to that transport closing and reopening. The retry logic is as follows:

  • Reverse connection is not configured => infinitely block on server connection
  • Reverse connection is configured
    • Reverse connection is successful => cache connection, set timeout to max (30s)
    • Reverse connection is unsuccessful or closed => set timeout to minimum (250ms) and poll on other connections, multiply by falloff factor (2) for each attempt until max (30s)

The runtime caches reverse connections so that it is not constantly attaching to the reverse transport every time poll times out or the server connection is used. These cache entries get cleared when a connection is used or the connection is hung up.

This PR is currently missing The following will be a separate PR:

  • Semantics for blocking startup of the runtime
    • To enable collecting startup events, we would add a configurable blocking timeout to runtime startup
    • an environment variable will take a value of -1 (infinite), or 0 to n milliseconds
    • this value will be used to determine how long to block eemain before an EventPipe session is started.
    • the default will be 0 (no block)

CC - @tommcdon@shirhatti@noahfalk@sywhang

@josalemjosalem added this to the 5.0 milestone Mar 6, 2020
@josalem
josalem requested review from noahfalk and sywhangMarch 6, 2020 22:28
@josalemjosalem self-assigned this Mar 6, 2020
@Dotnet-GitSync-Bot

Copy link
Copy Markdown
Collaborator

I couldn't add an area label to this PR.

Checkout this page to find out which area owner to ping, or please add exactly one area label to help train me in the future.

@noahfalknoahfalk 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.

Added a few comments and questions. Holding off on a more detailed review in expectation that things are still changing : )

Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/inc/clrconfigvalues.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsserverprotocolhelper.h Outdated
@josalem
josalem marked this pull request as ready for review March 18, 2020 00:06
@josalem
josalem requested a review from noahfalkMarch 18, 2020 00:06
@josalemjosalem changed the title [Draft] Add Reverse Diagnostics Server (client-mode)Add Reverse Diagnostics Server (client-mode)Mar 18, 2020

@noahfalknoahfalk 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.

Its shaping up but will still need some more work to be robust. Happy to chat if you've got questions about anything.

Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticserver.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated

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 would add an assert that that OVERLAPPED operation is complete. I would also test to confirm that DisconnectNamedPipe() finishes a ConnectNamedPipe operation when it is still pending. Destroying an OVERLAPPED struct before the operation ends usually causes painful to debug memory corruption issues.

Comment threadsrc/coreclr/src/vm/diagnosticsipcfactory.cpp Outdated
@josalem
josalemforce-pushed the dev/josalem/diag-server-handshake branch from 9f108d8 to 20f3745CompareApril 1, 2020 22:41

@noahfalknoahfalk 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.

Tests and functional correctness looking way better! I still have a few requests on the API design, performance, and additional tests but nothing as critical as the last iteration.

Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/vm/ipcstreamfactory.cpp Outdated
Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs
John Salem added 8 commits April 8, 2020 09:54
* Adds ConnectionState class for hiding server/client diff
* simplifies code for easier reading
* test was creating a pipe with a 0 buffer
* runtime needs to handle a 0 buffer namedpipe
* makes advertisement not block for more than 100 ms
* TODO: implement on non-windows
@josalem

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@josalem
josalem requested a review from noahfalkApril 17, 2020 22:18

@noahfalknoahfalk 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.

Alright, things are starting to look ship shape 👍 I did find a few more minor potential issues, comments inline.

Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp
Comment threadsrc/coreclr/src/debug/debug-pal/win/diagnosticsipc.cpp Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/debug/inc/diagnosticsipc.h Outdated
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h
Comment threadsrc/coreclr/src/vm/diagnosticsprotocol.h
Comment threadsrc/coreclr/src/vm/ipcstreamfactory.cpp
_pIpc->Close(callback);
if (_pStream != nullptr)
_pStream->Close(callback);
}

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.

_pIpc and _pStream need to be deleted (not that a leak on shutdown would really matter, but may as well clean up properly)

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I specifically leaked these since the PAL is unaware of shutdown paths and has access to these pointers. This method is specifically called from a different thread than the server thread. If we delete them in this code path it can lead to AVs on the server thread in the PAL (inside IpcStream::DiagnosticsIpc::Poll specifically). Rather than introduce some form of knowledge of runtime state to the PAL or potentially adding locks protecting access I opted to just leak the memory on shutdown, since that is the only place this method is called. I should add a comment that calls out this assumption, though.

Comment threadsrc/coreclr/tests/src/tracing/eventpipe/reverse/reverse.cs Outdated
@josalem

Copy link
Copy Markdown
ContributorAuthor

Remaining failure appears to be an AzDO Package Feed or NuGet manifest error. All test runs passed.

@josalemjosalem changed the title Add Reverse Diagnostics Server (client-mode)Add Reverse Diagnostics ServerApr 20, 2020
@josalem
josalem merged commit 629dba5 into dotnet:masterApr 20, 2020
jkotas added a commit that referenced this pull request May 3, 2020
jkotas added a commit that referenced this pull request May 3, 2020
josalem pushed a commit to josalem/runtime that referenced this pull request May 7, 2020
@ghostghost locked as resolved and limited conversation to collaborators Dec 10, 2020
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

@josalem@Dotnet-GitSync-Bot@noahfalk@tommcdon