Skip to content

Fixes issue when monitoring a process launched via the same command line - #76965

Merged
dramos020 merged 3 commits into
dotnet:mainfrom
dramos020:ProcessLaunchCountersBug
Oct 20, 2022
Merged

Fixes issue when monitoring a process launched via the same command line#76965
dramos020 merged 3 commits into
dotnet:mainfrom
dramos020:ProcessLaunchCountersBug

Conversation

@dramos020

@dramos020dramos020 commented Oct 12, 2022

Copy link
Copy Markdown
Contributor

Fixesdotnet/diagnostics#3366. A NullReferenceException was being thrown and caught because the CommandHandler in MetricsEventSource was being referenced before being initialized. Now custom metrics are displayed when trying to monitor a process in the same command line. Here is example output for a simple application with a custom meter that displays random values:

  • Running dotnet-counters monitor --counters System.Runtime,demo_meter -- countersbug.exe will now output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [System.Runtime]
    % Time in GC since last GC (%) 0
    Allocation Rate (B / 1 sec) 16,072
    CPU Usage (%) 0
    Exception Count (Count / 1 sec) 0
    GC Committed Bytes (MB) 0
    GC Fragmentation (%) 0
    GC Heap Size (MB) 0.462
    Gen 0 GC Count (Count / 1 sec) 0
    Gen 0 Size (B) 0
    Gen 1 GC Count (Count / 1 sec) 0
    Gen 1 Size (B) 0
    Gen 2 GC Count (Count / 1 sec) 0
    Gen 2 Size (B) 0
    IL Bytes Jitted (B) 47,239
    LOH Size (B) 0
    Monitor Lock Contention Count (Count / 1 sec) 0
    Number of Active Timers 0
    Number of Assemblies Loaded 13
    Number of Methods Jitted 438
    POH (Pinned Object Heap) Size (B) 0
    ThreadPool Completed Work Item Count (Count / 1 sec) 0
    ThreadPool Queue Length 0
    ThreadPool Thread Count 0
    Time spent in JIT (ms / 1 sec) 10.01
    Working Set (MB) 25.793
    [demo_meter]
    random (Count / 1 sec)
    instance=app -793.95
    
  • Running dotnet-counters monitor --counters demo_meter -- countersbug.exe will now output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [demo_meter]
    random (Count / 1 sec)
    instance=app 799.513
    

@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @tarekgh, @tommcdon, @pjanotti
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes dotnet/diagnostics#3366. A NullReferenceException was being thrown and caught because the CommandHandler in MetricsEventSource was being referenced before being initialized. Now custom metrics are displayed when trying to monitor a process in the same command line. Here is example output for a simple application with a custom meter that displays random values:

  • Running dotnet-counters monitor --counters System.Runtime,demo_meter -- countersbug.exe will output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [System.Runtime]
    % Time in GC since last GC (%) 0
    Allocation Rate (B / 1 sec) 16,072
    CPU Usage (%) 0
    Exception Count (Count / 1 sec) 0
    GC Committed Bytes (MB) 0
    GC Fragmentation (%) 0
    GC Heap Size (MB) 0.462
    Gen 0 GC Count (Count / 1 sec) 0
    Gen 0 Size (B) 0
    Gen 1 GC Count (Count / 1 sec) 0
    Gen 1 Size (B) 0
    Gen 2 GC Count (Count / 1 sec) 0
    Gen 2 Size (B) 0
    IL Bytes Jitted (B) 47,239
    LOH Size (B) 0
    Monitor Lock Contention Count (Count / 1 sec) 0
    Number of Active Timers 0
    Number of Assemblies Loaded 13
    Number of Methods Jitted 438
    POH (Pinned Object Heap) Size (B) 0
    ThreadPool Completed Work Item Count (Count / 1 sec) 0
    ThreadPool Queue Length 0
    ThreadPool Thread Count 0
    Time spent in JIT (ms / 1 sec) 10.01
    Working Set (MB) 25.793
    [demo_meter]
    random (Count / 1 sec)
    instance=app -793.95
    
  • Running dotnet-counters monitor --counters demo_meter -- countersbug.exe will output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [demo_meter]
    random (Count / 1 sec)
    instance=app 799.513
    
Author:dramos020
Assignees:-
Labels:

area-System.Diagnostics.Tracing

Milestone:-

@noahfalk

Copy link
Copy Markdown
Member

Can you include the callstack where the NullReferenceException occurs? A lot of the changes were swapping the Log property to a local parent field so does that also mean the static Log property was not initialized at that point? I want to understand what constraints we are working within :)

@davmason

davmason commented Oct 13, 2022

Copy link
Copy Markdown
Contributor

@noahfalk we're trying to grab the original exception but running in to technical difficulties.

The reason it fails is if you start a session before the runtime starts, you see the following scenario

  • MetricsEventSource static construct runs to initialize the Log object
  • It calls the base EventSource constructor, which sees a session is open and calls the OnEventCommand for MetricsEventSource from inside the EventSource constructor
  • Now we are calling in to MetricsEventSource before the static constructor has fully run and Log is assigned to so any call to Log will have a null reference

@noahfalk

Copy link
Copy Markdown
Member

Got it. What if we did something like this?

  1. When MetricsEventSource needs to access the command handler it can use a property and implement the property like this:
privateCommandHandlerHandler{get{if(_handler==null){Interlocked.CompareExchange(ref_handler,newCommandHandler(this),null);}returnhandler;}
  1. When CommandHandler needs to access the MetricsEventSource it can do that through a property that was initialized in the CommandHandler constructor:
publicCommandHandler(MetricsEventSource parent){Parent=parent;}publicMetricsEventSourceParent{get;}// some code that needs to use parentParent.Error("Something bad happened");

@davmason

Copy link
Copy Markdown
Contributor

Works for me

@dramos020

dramos020 commented Oct 14, 2022

Copy link
Copy Markdown
ContributorAuthor

Just made the changes that were suggested. @noahfalk@davmason

@dramos020
dramos020 marked this pull request as ready for review October 14, 2022 21:16

@davmasondavmason left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@dramos020
dramos020 merged commit a32feb0 into dotnet:mainOct 20, 2022
@ghostghost locked as resolved and limited conversation to collaborators Nov 19, 2022
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.

dotnet-counters issue when monitoring a process launched via the same command-line

3 participants

@dramos020@noahfalk@davmason
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
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;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Fixes issue when monitoring a process launched via the same command line by dramos020 · Pull Request #76965 · dotnet/runtime · GitHub
Skip to content

Fixes issue when monitoring a process launched via the same command line - #76965

Merged
dramos020 merged 3 commits into
dotnet:mainfrom
dramos020:ProcessLaunchCountersBug
Oct 20, 2022
Merged

Fixes issue when monitoring a process launched via the same command line#76965
dramos020 merged 3 commits into
dotnet:mainfrom
dramos020:ProcessLaunchCountersBug

Conversation

@dramos020

@dramos020dramos020 commented Oct 12, 2022

Copy link
Copy Markdown
Contributor

Fixesdotnet/diagnostics#3366. A NullReferenceException was being thrown and caught because the CommandHandler in MetricsEventSource was being referenced before being initialized. Now custom metrics are displayed when trying to monitor a process in the same command line. Here is example output for a simple application with a custom meter that displays random values:

  • Running dotnet-counters monitor --counters System.Runtime,demo_meter -- countersbug.exe will now output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [System.Runtime]
    % Time in GC since last GC (%) 0
    Allocation Rate (B / 1 sec) 16,072
    CPU Usage (%) 0
    Exception Count (Count / 1 sec) 0
    GC Committed Bytes (MB) 0
    GC Fragmentation (%) 0
    GC Heap Size (MB) 0.462
    Gen 0 GC Count (Count / 1 sec) 0
    Gen 0 Size (B) 0
    Gen 1 GC Count (Count / 1 sec) 0
    Gen 1 Size (B) 0
    Gen 2 GC Count (Count / 1 sec) 0
    Gen 2 Size (B) 0
    IL Bytes Jitted (B) 47,239
    LOH Size (B) 0
    Monitor Lock Contention Count (Count / 1 sec) 0
    Number of Active Timers 0
    Number of Assemblies Loaded 13
    Number of Methods Jitted 438
    POH (Pinned Object Heap) Size (B) 0
    ThreadPool Completed Work Item Count (Count / 1 sec) 0
    ThreadPool Queue Length 0
    ThreadPool Thread Count 0
    Time spent in JIT (ms / 1 sec) 10.01
    Working Set (MB) 25.793
    [demo_meter]
    random (Count / 1 sec)
    instance=app -793.95
    
  • Running dotnet-counters monitor --counters demo_meter -- countersbug.exe will now output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [demo_meter]
    random (Count / 1 sec)
    instance=app 799.513
    

@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @tarekgh, @tommcdon, @pjanotti
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes dotnet/diagnostics#3366. A NullReferenceException was being thrown and caught because the CommandHandler in MetricsEventSource was being referenced before being initialized. Now custom metrics are displayed when trying to monitor a process in the same command line. Here is example output for a simple application with a custom meter that displays random values:

  • Running dotnet-counters monitor --counters System.Runtime,demo_meter -- countersbug.exe will output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [System.Runtime]
    % Time in GC since last GC (%) 0
    Allocation Rate (B / 1 sec) 16,072
    CPU Usage (%) 0
    Exception Count (Count / 1 sec) 0
    GC Committed Bytes (MB) 0
    GC Fragmentation (%) 0
    GC Heap Size (MB) 0.462
    Gen 0 GC Count (Count / 1 sec) 0
    Gen 0 Size (B) 0
    Gen 1 GC Count (Count / 1 sec) 0
    Gen 1 Size (B) 0
    Gen 2 GC Count (Count / 1 sec) 0
    Gen 2 Size (B) 0
    IL Bytes Jitted (B) 47,239
    LOH Size (B) 0
    Monitor Lock Contention Count (Count / 1 sec) 0
    Number of Active Timers 0
    Number of Assemblies Loaded 13
    Number of Methods Jitted 438
    POH (Pinned Object Heap) Size (B) 0
    ThreadPool Completed Work Item Count (Count / 1 sec) 0
    ThreadPool Queue Length 0
    ThreadPool Thread Count 0
    Time spent in JIT (ms / 1 sec) 10.01
    Working Set (MB) 25.793
    [demo_meter]
    random (Count / 1 sec)
    instance=app -793.95
    
  • Running dotnet-counters monitor --counters demo_meter -- countersbug.exe will output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [demo_meter]
    random (Count / 1 sec)
    instance=app 799.513
    
Author:dramos020
Assignees:-
Labels:

area-System.Diagnostics.Tracing

Milestone:-

@noahfalk

Copy link
Copy Markdown
Member

Can you include the callstack where the NullReferenceException occurs? A lot of the changes were swapping the Log property to a local parent field so does that also mean the static Log property was not initialized at that point? I want to understand what constraints we are working within :)

@davmason

davmason commented Oct 13, 2022

Copy link
Copy Markdown
Contributor

@noahfalk we're trying to grab the original exception but running in to technical difficulties.

The reason it fails is if you start a session before the runtime starts, you see the following scenario

  • MetricsEventSource static construct runs to initialize the Log object
  • It calls the base EventSource constructor, which sees a session is open and calls the OnEventCommand for MetricsEventSource from inside the EventSource constructor
  • Now we are calling in to MetricsEventSource before the static constructor has fully run and Log is assigned to so any call to Log will have a null reference

@noahfalk

Copy link
Copy Markdown
Member

Got it. What if we did something like this?

  1. When MetricsEventSource needs to access the command handler it can use a property and implement the property like this:
privateCommandHandlerHandler{get{if(_handler==null){Interlocked.CompareExchange(ref_handler,newCommandHandler(this),null);}returnhandler;}
  1. When CommandHandler needs to access the MetricsEventSource it can do that through a property that was initialized in the CommandHandler constructor:
publicCommandHandler(MetricsEventSource parent){Parent=parent;}publicMetricsEventSourceParent{get;}// some code that needs to use parentParent.Error("Something bad happened");

@davmason

Copy link
Copy Markdown
Contributor

Works for me

@dramos020

dramos020 commented Oct 14, 2022

Copy link
Copy Markdown
ContributorAuthor

Just made the changes that were suggested. @noahfalk@davmason

@dramos020
dramos020 marked this pull request as ready for review October 14, 2022 21:16

@davmasondavmason left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@dramos020
dramos020 merged commit a32feb0 into dotnet:mainOct 20, 2022
@ghostghost locked as resolved and limited conversation to collaborators Nov 19, 2022
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.

dotnet-counters issue when monitoring a process launched via the same command-line

3 participants

@dramos020@noahfalk@davmason
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Fixes issue when monitoring a process launched via the same command line by dramos020 · Pull Request #76965 · dotnet/runtime · GitHub
Skip to content

Fixes issue when monitoring a process launched via the same command line - #76965

Merged
dramos020 merged 3 commits into
dotnet:mainfrom
dramos020:ProcessLaunchCountersBug
Oct 20, 2022
Merged

Fixes issue when monitoring a process launched via the same command line#76965
dramos020 merged 3 commits into
dotnet:mainfrom
dramos020:ProcessLaunchCountersBug

Conversation

@dramos020

@dramos020dramos020 commented Oct 12, 2022

Copy link
Copy Markdown
Contributor

Fixesdotnet/diagnostics#3366. A NullReferenceException was being thrown and caught because the CommandHandler in MetricsEventSource was being referenced before being initialized. Now custom metrics are displayed when trying to monitor a process in the same command line. Here is example output for a simple application with a custom meter that displays random values:

  • Running dotnet-counters monitor --counters System.Runtime,demo_meter -- countersbug.exe will now output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [System.Runtime]
    % Time in GC since last GC (%) 0
    Allocation Rate (B / 1 sec) 16,072
    CPU Usage (%) 0
    Exception Count (Count / 1 sec) 0
    GC Committed Bytes (MB) 0
    GC Fragmentation (%) 0
    GC Heap Size (MB) 0.462
    Gen 0 GC Count (Count / 1 sec) 0
    Gen 0 Size (B) 0
    Gen 1 GC Count (Count / 1 sec) 0
    Gen 1 Size (B) 0
    Gen 2 GC Count (Count / 1 sec) 0
    Gen 2 Size (B) 0
    IL Bytes Jitted (B) 47,239
    LOH Size (B) 0
    Monitor Lock Contention Count (Count / 1 sec) 0
    Number of Active Timers 0
    Number of Assemblies Loaded 13
    Number of Methods Jitted 438
    POH (Pinned Object Heap) Size (B) 0
    ThreadPool Completed Work Item Count (Count / 1 sec) 0
    ThreadPool Queue Length 0
    ThreadPool Thread Count 0
    Time spent in JIT (ms / 1 sec) 10.01
    Working Set (MB) 25.793
    [demo_meter]
    random (Count / 1 sec)
    instance=app -793.95
    
  • Running dotnet-counters monitor --counters demo_meter -- countersbug.exe will now output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [demo_meter]
    random (Count / 1 sec)
    instance=app 799.513
    

@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @tarekgh, @tommcdon, @pjanotti
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes dotnet/diagnostics#3366. A NullReferenceException was being thrown and caught because the CommandHandler in MetricsEventSource was being referenced before being initialized. Now custom metrics are displayed when trying to monitor a process in the same command line. Here is example output for a simple application with a custom meter that displays random values:

  • Running dotnet-counters monitor --counters System.Runtime,demo_meter -- countersbug.exe will output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [System.Runtime]
    % Time in GC since last GC (%) 0
    Allocation Rate (B / 1 sec) 16,072
    CPU Usage (%) 0
    Exception Count (Count / 1 sec) 0
    GC Committed Bytes (MB) 0
    GC Fragmentation (%) 0
    GC Heap Size (MB) 0.462
    Gen 0 GC Count (Count / 1 sec) 0
    Gen 0 Size (B) 0
    Gen 1 GC Count (Count / 1 sec) 0
    Gen 1 Size (B) 0
    Gen 2 GC Count (Count / 1 sec) 0
    Gen 2 Size (B) 0
    IL Bytes Jitted (B) 47,239
    LOH Size (B) 0
    Monitor Lock Contention Count (Count / 1 sec) 0
    Number of Active Timers 0
    Number of Assemblies Loaded 13
    Number of Methods Jitted 438
    POH (Pinned Object Heap) Size (B) 0
    ThreadPool Completed Work Item Count (Count / 1 sec) 0
    ThreadPool Queue Length 0
    ThreadPool Thread Count 0
    Time spent in JIT (ms / 1 sec) 10.01
    Working Set (MB) 25.793
    [demo_meter]
    random (Count / 1 sec)
    instance=app -793.95
    
  • Running dotnet-counters monitor --counters demo_meter -- countersbug.exe will output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [demo_meter]
    random (Count / 1 sec)
    instance=app 799.513
    
Author:dramos020
Assignees:-
Labels:

area-System.Diagnostics.Tracing

Milestone:-

@noahfalk

Copy link
Copy Markdown
Member

Can you include the callstack where the NullReferenceException occurs? A lot of the changes were swapping the Log property to a local parent field so does that also mean the static Log property was not initialized at that point? I want to understand what constraints we are working within :)

@davmason

davmason commented Oct 13, 2022

Copy link
Copy Markdown
Contributor

@noahfalk we're trying to grab the original exception but running in to technical difficulties.

The reason it fails is if you start a session before the runtime starts, you see the following scenario

  • MetricsEventSource static construct runs to initialize the Log object
  • It calls the base EventSource constructor, which sees a session is open and calls the OnEventCommand for MetricsEventSource from inside the EventSource constructor
  • Now we are calling in to MetricsEventSource before the static constructor has fully run and Log is assigned to so any call to Log will have a null reference

@noahfalk

Copy link
Copy Markdown
Member

Got it. What if we did something like this?

  1. When MetricsEventSource needs to access the command handler it can use a property and implement the property like this:
privateCommandHandlerHandler{get{if(_handler==null){Interlocked.CompareExchange(ref_handler,newCommandHandler(this),null);}returnhandler;}
  1. When CommandHandler needs to access the MetricsEventSource it can do that through a property that was initialized in the CommandHandler constructor:
publicCommandHandler(MetricsEventSource parent){Parent=parent;}publicMetricsEventSourceParent{get;}// some code that needs to use parentParent.Error("Something bad happened");

@davmason

Copy link
Copy Markdown
Contributor

Works for me

@dramos020

dramos020 commented Oct 14, 2022

Copy link
Copy Markdown
ContributorAuthor

Just made the changes that were suggested. @noahfalk@davmason

@dramos020
dramos020 marked this pull request as ready for review October 14, 2022 21:16

@davmasondavmason left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@dramos020
dramos020 merged commit a32feb0 into dotnet:mainOct 20, 2022
@ghostghost locked as resolved and limited conversation to collaborators Nov 19, 2022
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.

dotnet-counters issue when monitoring a process launched via the same command-line

3 participants

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

Fixes issue when monitoring a process launched via the same command line - #76965

Merged
dramos020 merged 3 commits into
dotnet:mainfrom
dramos020:ProcessLaunchCountersBug
Oct 20, 2022
Merged

Fixes issue when monitoring a process launched via the same command line#76965
dramos020 merged 3 commits into
dotnet:mainfrom
dramos020:ProcessLaunchCountersBug

Conversation

@dramos020

@dramos020dramos020 commented Oct 12, 2022

Copy link
Copy Markdown
Contributor

Fixesdotnet/diagnostics#3366. A NullReferenceException was being thrown and caught because the CommandHandler in MetricsEventSource was being referenced before being initialized. Now custom metrics are displayed when trying to monitor a process in the same command line. Here is example output for a simple application with a custom meter that displays random values:

  • Running dotnet-counters monitor --counters System.Runtime,demo_meter -- countersbug.exe will now output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [System.Runtime]
    % Time in GC since last GC (%) 0
    Allocation Rate (B / 1 sec) 16,072
    CPU Usage (%) 0
    Exception Count (Count / 1 sec) 0
    GC Committed Bytes (MB) 0
    GC Fragmentation (%) 0
    GC Heap Size (MB) 0.462
    Gen 0 GC Count (Count / 1 sec) 0
    Gen 0 Size (B) 0
    Gen 1 GC Count (Count / 1 sec) 0
    Gen 1 Size (B) 0
    Gen 2 GC Count (Count / 1 sec) 0
    Gen 2 Size (B) 0
    IL Bytes Jitted (B) 47,239
    LOH Size (B) 0
    Monitor Lock Contention Count (Count / 1 sec) 0
    Number of Active Timers 0
    Number of Assemblies Loaded 13
    Number of Methods Jitted 438
    POH (Pinned Object Heap) Size (B) 0
    ThreadPool Completed Work Item Count (Count / 1 sec) 0
    ThreadPool Queue Length 0
    ThreadPool Thread Count 0
    Time spent in JIT (ms / 1 sec) 10.01
    Working Set (MB) 25.793
    [demo_meter]
    random (Count / 1 sec)
    instance=app -793.95
    
  • Running dotnet-counters monitor --counters demo_meter -- countersbug.exe will now output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [demo_meter]
    random (Count / 1 sec)
    instance=app 799.513
    

@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @tarekgh, @tommcdon, @pjanotti
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes dotnet/diagnostics#3366. A NullReferenceException was being thrown and caught because the CommandHandler in MetricsEventSource was being referenced before being initialized. Now custom metrics are displayed when trying to monitor a process in the same command line. Here is example output for a simple application with a custom meter that displays random values:

  • Running dotnet-counters monitor --counters System.Runtime,demo_meter -- countersbug.exe will output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [System.Runtime]
    % Time in GC since last GC (%) 0
    Allocation Rate (B / 1 sec) 16,072
    CPU Usage (%) 0
    Exception Count (Count / 1 sec) 0
    GC Committed Bytes (MB) 0
    GC Fragmentation (%) 0
    GC Heap Size (MB) 0.462
    Gen 0 GC Count (Count / 1 sec) 0
    Gen 0 Size (B) 0
    Gen 1 GC Count (Count / 1 sec) 0
    Gen 1 Size (B) 0
    Gen 2 GC Count (Count / 1 sec) 0
    Gen 2 Size (B) 0
    IL Bytes Jitted (B) 47,239
    LOH Size (B) 0
    Monitor Lock Contention Count (Count / 1 sec) 0
    Number of Active Timers 0
    Number of Assemblies Loaded 13
    Number of Methods Jitted 438
    POH (Pinned Object Heap) Size (B) 0
    ThreadPool Completed Work Item Count (Count / 1 sec) 0
    ThreadPool Queue Length 0
    ThreadPool Thread Count 0
    Time spent in JIT (ms / 1 sec) 10.01
    Working Set (MB) 25.793
    [demo_meter]
    random (Count / 1 sec)
    instance=app -793.95
    
  • Running dotnet-counters monitor --counters demo_meter -- countersbug.exe will output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [demo_meter]
    random (Count / 1 sec)
    instance=app 799.513
    
Author:dramos020
Assignees:-
Labels:

area-System.Diagnostics.Tracing

Milestone:-

@noahfalk

Copy link
Copy Markdown
Member

Can you include the callstack where the NullReferenceException occurs? A lot of the changes were swapping the Log property to a local parent field so does that also mean the static Log property was not initialized at that point? I want to understand what constraints we are working within :)

@davmason

davmason commented Oct 13, 2022

Copy link
Copy Markdown
Contributor

@noahfalk we're trying to grab the original exception but running in to technical difficulties.

The reason it fails is if you start a session before the runtime starts, you see the following scenario

  • MetricsEventSource static construct runs to initialize the Log object
  • It calls the base EventSource constructor, which sees a session is open and calls the OnEventCommand for MetricsEventSource from inside the EventSource constructor
  • Now we are calling in to MetricsEventSource before the static constructor has fully run and Log is assigned to so any call to Log will have a null reference

@noahfalk

Copy link
Copy Markdown
Member

Got it. What if we did something like this?

  1. When MetricsEventSource needs to access the command handler it can use a property and implement the property like this:
privateCommandHandlerHandler{get{if(_handler==null){Interlocked.CompareExchange(ref_handler,newCommandHandler(this),null);}returnhandler;}
  1. When CommandHandler needs to access the MetricsEventSource it can do that through a property that was initialized in the CommandHandler constructor:
publicCommandHandler(MetricsEventSource parent){Parent=parent;}publicMetricsEventSourceParent{get;}// some code that needs to use parentParent.Error("Something bad happened");

@davmason

Copy link
Copy Markdown
Contributor

Works for me

@dramos020

dramos020 commented Oct 14, 2022

Copy link
Copy Markdown
ContributorAuthor

Just made the changes that were suggested. @noahfalk@davmason

@dramos020
dramos020 marked this pull request as ready for review October 14, 2022 21:16

@davmasondavmason left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@dramos020
dramos020 merged commit a32feb0 into dotnet:mainOct 20, 2022
@ghostghost locked as resolved and limited conversation to collaborators Nov 19, 2022
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.

dotnet-counters issue when monitoring a process launched via the same command-line

3 participants

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

Fixes issue when monitoring a process launched via the same command line - #76965

Merged
dramos020 merged 3 commits into
dotnet:mainfrom
dramos020:ProcessLaunchCountersBug
Oct 20, 2022
Merged

Fixes issue when monitoring a process launched via the same command line#76965
dramos020 merged 3 commits into
dotnet:mainfrom
dramos020:ProcessLaunchCountersBug

Conversation

@dramos020

@dramos020dramos020 commented Oct 12, 2022

Copy link
Copy Markdown
Contributor

Fixesdotnet/diagnostics#3366. A NullReferenceException was being thrown and caught because the CommandHandler in MetricsEventSource was being referenced before being initialized. Now custom metrics are displayed when trying to monitor a process in the same command line. Here is example output for a simple application with a custom meter that displays random values:

  • Running dotnet-counters monitor --counters System.Runtime,demo_meter -- countersbug.exe will now output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [System.Runtime]
    % Time in GC since last GC (%) 0
    Allocation Rate (B / 1 sec) 16,072
    CPU Usage (%) 0
    Exception Count (Count / 1 sec) 0
    GC Committed Bytes (MB) 0
    GC Fragmentation (%) 0
    GC Heap Size (MB) 0.462
    Gen 0 GC Count (Count / 1 sec) 0
    Gen 0 Size (B) 0
    Gen 1 GC Count (Count / 1 sec) 0
    Gen 1 Size (B) 0
    Gen 2 GC Count (Count / 1 sec) 0
    Gen 2 Size (B) 0
    IL Bytes Jitted (B) 47,239
    LOH Size (B) 0
    Monitor Lock Contention Count (Count / 1 sec) 0
    Number of Active Timers 0
    Number of Assemblies Loaded 13
    Number of Methods Jitted 438
    POH (Pinned Object Heap) Size (B) 0
    ThreadPool Completed Work Item Count (Count / 1 sec) 0
    ThreadPool Queue Length 0
    ThreadPool Thread Count 0
    Time spent in JIT (ms / 1 sec) 10.01
    Working Set (MB) 25.793
    [demo_meter]
    random (Count / 1 sec)
    instance=app -793.95
    
  • Running dotnet-counters monitor --counters demo_meter -- countersbug.exe will now output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [demo_meter]
    random (Count / 1 sec)
    instance=app 799.513
    

@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @tarekgh, @tommcdon, @pjanotti
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes dotnet/diagnostics#3366. A NullReferenceException was being thrown and caught because the CommandHandler in MetricsEventSource was being referenced before being initialized. Now custom metrics are displayed when trying to monitor a process in the same command line. Here is example output for a simple application with a custom meter that displays random values:

  • Running dotnet-counters monitor --counters System.Runtime,demo_meter -- countersbug.exe will output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [System.Runtime]
    % Time in GC since last GC (%) 0
    Allocation Rate (B / 1 sec) 16,072
    CPU Usage (%) 0
    Exception Count (Count / 1 sec) 0
    GC Committed Bytes (MB) 0
    GC Fragmentation (%) 0
    GC Heap Size (MB) 0.462
    Gen 0 GC Count (Count / 1 sec) 0
    Gen 0 Size (B) 0
    Gen 1 GC Count (Count / 1 sec) 0
    Gen 1 Size (B) 0
    Gen 2 GC Count (Count / 1 sec) 0
    Gen 2 Size (B) 0
    IL Bytes Jitted (B) 47,239
    LOH Size (B) 0
    Monitor Lock Contention Count (Count / 1 sec) 0
    Number of Active Timers 0
    Number of Assemblies Loaded 13
    Number of Methods Jitted 438
    POH (Pinned Object Heap) Size (B) 0
    ThreadPool Completed Work Item Count (Count / 1 sec) 0
    ThreadPool Queue Length 0
    ThreadPool Thread Count 0
    Time spent in JIT (ms / 1 sec) 10.01
    Working Set (MB) 25.793
    [demo_meter]
    random (Count / 1 sec)
    instance=app -793.95
    
  • Running dotnet-counters monitor --counters demo_meter -- countersbug.exe will output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [demo_meter]
    random (Count / 1 sec)
    instance=app 799.513
    
Author:dramos020
Assignees:-
Labels:

area-System.Diagnostics.Tracing

Milestone:-

@noahfalk

Copy link
Copy Markdown
Member

Can you include the callstack where the NullReferenceException occurs? A lot of the changes were swapping the Log property to a local parent field so does that also mean the static Log property was not initialized at that point? I want to understand what constraints we are working within :)

@davmason

davmason commented Oct 13, 2022

Copy link
Copy Markdown
Contributor

@noahfalk we're trying to grab the original exception but running in to technical difficulties.

The reason it fails is if you start a session before the runtime starts, you see the following scenario

  • MetricsEventSource static construct runs to initialize the Log object
  • It calls the base EventSource constructor, which sees a session is open and calls the OnEventCommand for MetricsEventSource from inside the EventSource constructor
  • Now we are calling in to MetricsEventSource before the static constructor has fully run and Log is assigned to so any call to Log will have a null reference

@noahfalk

Copy link
Copy Markdown
Member

Got it. What if we did something like this?

  1. When MetricsEventSource needs to access the command handler it can use a property and implement the property like this:
privateCommandHandlerHandler{get{if(_handler==null){Interlocked.CompareExchange(ref_handler,newCommandHandler(this),null);}returnhandler;}
  1. When CommandHandler needs to access the MetricsEventSource it can do that through a property that was initialized in the CommandHandler constructor:
publicCommandHandler(MetricsEventSource parent){Parent=parent;}publicMetricsEventSourceParent{get;}// some code that needs to use parentParent.Error("Something bad happened");

@davmason

Copy link
Copy Markdown
Contributor

Works for me

@dramos020

dramos020 commented Oct 14, 2022

Copy link
Copy Markdown
ContributorAuthor

Just made the changes that were suggested. @noahfalk@davmason

@dramos020
dramos020 marked this pull request as ready for review October 14, 2022 21:16

@davmasondavmason left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@dramos020
dramos020 merged commit a32feb0 into dotnet:mainOct 20, 2022
@ghostghost locked as resolved and limited conversation to collaborators Nov 19, 2022
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.

dotnet-counters issue when monitoring a process launched via the same command-line

3 participants

@dramos020@noahfalk@davmason
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Fixes issue when monitoring a process launched via the same command line by dramos020 · Pull Request #76965 · dotnet/runtime · GitHub
Skip to content

Fixes issue when monitoring a process launched via the same command line - #76965

Merged
dramos020 merged 3 commits into
dotnet:mainfrom
dramos020:ProcessLaunchCountersBug
Oct 20, 2022
Merged

Fixes issue when monitoring a process launched via the same command line#76965
dramos020 merged 3 commits into
dotnet:mainfrom
dramos020:ProcessLaunchCountersBug

Conversation

@dramos020

@dramos020dramos020 commented Oct 12, 2022

Copy link
Copy Markdown
Contributor

Fixesdotnet/diagnostics#3366. A NullReferenceException was being thrown and caught because the CommandHandler in MetricsEventSource was being referenced before being initialized. Now custom metrics are displayed when trying to monitor a process in the same command line. Here is example output for a simple application with a custom meter that displays random values:

  • Running dotnet-counters monitor --counters System.Runtime,demo_meter -- countersbug.exe will now output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [System.Runtime]
    % Time in GC since last GC (%) 0
    Allocation Rate (B / 1 sec) 16,072
    CPU Usage (%) 0
    Exception Count (Count / 1 sec) 0
    GC Committed Bytes (MB) 0
    GC Fragmentation (%) 0
    GC Heap Size (MB) 0.462
    Gen 0 GC Count (Count / 1 sec) 0
    Gen 0 Size (B) 0
    Gen 1 GC Count (Count / 1 sec) 0
    Gen 1 Size (B) 0
    Gen 2 GC Count (Count / 1 sec) 0
    Gen 2 Size (B) 0
    IL Bytes Jitted (B) 47,239
    LOH Size (B) 0
    Monitor Lock Contention Count (Count / 1 sec) 0
    Number of Active Timers 0
    Number of Assemblies Loaded 13
    Number of Methods Jitted 438
    POH (Pinned Object Heap) Size (B) 0
    ThreadPool Completed Work Item Count (Count / 1 sec) 0
    ThreadPool Queue Length 0
    ThreadPool Thread Count 0
    Time spent in JIT (ms / 1 sec) 10.01
    Working Set (MB) 25.793
    [demo_meter]
    random (Count / 1 sec)
    instance=app -793.95
    
  • Running dotnet-counters monitor --counters demo_meter -- countersbug.exe will now output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [demo_meter]
    random (Count / 1 sec)
    instance=app 799.513
    

@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @tarekgh, @tommcdon, @pjanotti
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes dotnet/diagnostics#3366. A NullReferenceException was being thrown and caught because the CommandHandler in MetricsEventSource was being referenced before being initialized. Now custom metrics are displayed when trying to monitor a process in the same command line. Here is example output for a simple application with a custom meter that displays random values:

  • Running dotnet-counters monitor --counters System.Runtime,demo_meter -- countersbug.exe will output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [System.Runtime]
    % Time in GC since last GC (%) 0
    Allocation Rate (B / 1 sec) 16,072
    CPU Usage (%) 0
    Exception Count (Count / 1 sec) 0
    GC Committed Bytes (MB) 0
    GC Fragmentation (%) 0
    GC Heap Size (MB) 0.462
    Gen 0 GC Count (Count / 1 sec) 0
    Gen 0 Size (B) 0
    Gen 1 GC Count (Count / 1 sec) 0
    Gen 1 Size (B) 0
    Gen 2 GC Count (Count / 1 sec) 0
    Gen 2 Size (B) 0
    IL Bytes Jitted (B) 47,239
    LOH Size (B) 0
    Monitor Lock Contention Count (Count / 1 sec) 0
    Number of Active Timers 0
    Number of Assemblies Loaded 13
    Number of Methods Jitted 438
    POH (Pinned Object Heap) Size (B) 0
    ThreadPool Completed Work Item Count (Count / 1 sec) 0
    ThreadPool Queue Length 0
    ThreadPool Thread Count 0
    Time spent in JIT (ms / 1 sec) 10.01
    Working Set (MB) 25.793
    [demo_meter]
    random (Count / 1 sec)
    instance=app -793.95
    
  • Running dotnet-counters monitor --counters demo_meter -- countersbug.exe will output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [demo_meter]
    random (Count / 1 sec)
    instance=app 799.513
    
Author:dramos020
Assignees:-
Labels:

area-System.Diagnostics.Tracing

Milestone:-

@noahfalk

Copy link
Copy Markdown
Member

Can you include the callstack where the NullReferenceException occurs? A lot of the changes were swapping the Log property to a local parent field so does that also mean the static Log property was not initialized at that point? I want to understand what constraints we are working within :)

@davmason

davmason commented Oct 13, 2022

Copy link
Copy Markdown
Contributor

@noahfalk we're trying to grab the original exception but running in to technical difficulties.

The reason it fails is if you start a session before the runtime starts, you see the following scenario

  • MetricsEventSource static construct runs to initialize the Log object
  • It calls the base EventSource constructor, which sees a session is open and calls the OnEventCommand for MetricsEventSource from inside the EventSource constructor
  • Now we are calling in to MetricsEventSource before the static constructor has fully run and Log is assigned to so any call to Log will have a null reference

@noahfalk

Copy link
Copy Markdown
Member

Got it. What if we did something like this?

  1. When MetricsEventSource needs to access the command handler it can use a property and implement the property like this:
privateCommandHandlerHandler{get{if(_handler==null){Interlocked.CompareExchange(ref_handler,newCommandHandler(this),null);}returnhandler;}
  1. When CommandHandler needs to access the MetricsEventSource it can do that through a property that was initialized in the CommandHandler constructor:
publicCommandHandler(MetricsEventSource parent){Parent=parent;}publicMetricsEventSourceParent{get;}// some code that needs to use parentParent.Error("Something bad happened");

@davmason

Copy link
Copy Markdown
Contributor

Works for me

@dramos020

dramos020 commented Oct 14, 2022

Copy link
Copy Markdown
ContributorAuthor

Just made the changes that were suggested. @noahfalk@davmason

@dramos020
dramos020 marked this pull request as ready for review October 14, 2022 21:16

@davmasondavmason left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@dramos020
dramos020 merged commit a32feb0 into dotnet:mainOct 20, 2022
@ghostghost locked as resolved and limited conversation to collaborators Nov 19, 2022
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.

dotnet-counters issue when monitoring a process launched via the same command-line

3 participants

@dramos020@noahfalk@davmason
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Fixes issue when monitoring a process launched via the same command line by dramos020 · Pull Request #76965 · dotnet/runtime · GitHub
Skip to content

Fixes issue when monitoring a process launched via the same command line - #76965

Merged
dramos020 merged 3 commits into
dotnet:mainfrom
dramos020:ProcessLaunchCountersBug
Oct 20, 2022
Merged

Fixes issue when monitoring a process launched via the same command line#76965
dramos020 merged 3 commits into
dotnet:mainfrom
dramos020:ProcessLaunchCountersBug

Conversation

@dramos020

@dramos020dramos020 commented Oct 12, 2022

Copy link
Copy Markdown
Contributor

Fixesdotnet/diagnostics#3366. A NullReferenceException was being thrown and caught because the CommandHandler in MetricsEventSource was being referenced before being initialized. Now custom metrics are displayed when trying to monitor a process in the same command line. Here is example output for a simple application with a custom meter that displays random values:

  • Running dotnet-counters monitor --counters System.Runtime,demo_meter -- countersbug.exe will now output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [System.Runtime]
    % Time in GC since last GC (%) 0
    Allocation Rate (B / 1 sec) 16,072
    CPU Usage (%) 0
    Exception Count (Count / 1 sec) 0
    GC Committed Bytes (MB) 0
    GC Fragmentation (%) 0
    GC Heap Size (MB) 0.462
    Gen 0 GC Count (Count / 1 sec) 0
    Gen 0 Size (B) 0
    Gen 1 GC Count (Count / 1 sec) 0
    Gen 1 Size (B) 0
    Gen 2 GC Count (Count / 1 sec) 0
    Gen 2 Size (B) 0
    IL Bytes Jitted (B) 47,239
    LOH Size (B) 0
    Monitor Lock Contention Count (Count / 1 sec) 0
    Number of Active Timers 0
    Number of Assemblies Loaded 13
    Number of Methods Jitted 438
    POH (Pinned Object Heap) Size (B) 0
    ThreadPool Completed Work Item Count (Count / 1 sec) 0
    ThreadPool Queue Length 0
    ThreadPool Thread Count 0
    Time spent in JIT (ms / 1 sec) 10.01
    Working Set (MB) 25.793
    [demo_meter]
    random (Count / 1 sec)
    instance=app -793.95
    
  • Running dotnet-counters monitor --counters demo_meter -- countersbug.exe will now output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [demo_meter]
    random (Count / 1 sec)
    instance=app 799.513
    

@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @tarekgh, @tommcdon, @pjanotti
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes dotnet/diagnostics#3366. A NullReferenceException was being thrown and caught because the CommandHandler in MetricsEventSource was being referenced before being initialized. Now custom metrics are displayed when trying to monitor a process in the same command line. Here is example output for a simple application with a custom meter that displays random values:

  • Running dotnet-counters monitor --counters System.Runtime,demo_meter -- countersbug.exe will output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [System.Runtime]
    % Time in GC since last GC (%) 0
    Allocation Rate (B / 1 sec) 16,072
    CPU Usage (%) 0
    Exception Count (Count / 1 sec) 0
    GC Committed Bytes (MB) 0
    GC Fragmentation (%) 0
    GC Heap Size (MB) 0.462
    Gen 0 GC Count (Count / 1 sec) 0
    Gen 0 Size (B) 0
    Gen 1 GC Count (Count / 1 sec) 0
    Gen 1 Size (B) 0
    Gen 2 GC Count (Count / 1 sec) 0
    Gen 2 Size (B) 0
    IL Bytes Jitted (B) 47,239
    LOH Size (B) 0
    Monitor Lock Contention Count (Count / 1 sec) 0
    Number of Active Timers 0
    Number of Assemblies Loaded 13
    Number of Methods Jitted 438
    POH (Pinned Object Heap) Size (B) 0
    ThreadPool Completed Work Item Count (Count / 1 sec) 0
    ThreadPool Queue Length 0
    ThreadPool Thread Count 0
    Time spent in JIT (ms / 1 sec) 10.01
    Working Set (MB) 25.793
    [demo_meter]
    random (Count / 1 sec)
    instance=app -793.95
    
  • Running dotnet-counters monitor --counters demo_meter -- countersbug.exe will output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [demo_meter]
    random (Count / 1 sec)
    instance=app 799.513
    
Author:dramos020
Assignees:-
Labels:

area-System.Diagnostics.Tracing

Milestone:-

@noahfalk

Copy link
Copy Markdown
Member

Can you include the callstack where the NullReferenceException occurs? A lot of the changes were swapping the Log property to a local parent field so does that also mean the static Log property was not initialized at that point? I want to understand what constraints we are working within :)

@davmason

davmason commented Oct 13, 2022

Copy link
Copy Markdown
Contributor

@noahfalk we're trying to grab the original exception but running in to technical difficulties.

The reason it fails is if you start a session before the runtime starts, you see the following scenario

  • MetricsEventSource static construct runs to initialize the Log object
  • It calls the base EventSource constructor, which sees a session is open and calls the OnEventCommand for MetricsEventSource from inside the EventSource constructor
  • Now we are calling in to MetricsEventSource before the static constructor has fully run and Log is assigned to so any call to Log will have a null reference

@noahfalk

Copy link
Copy Markdown
Member

Got it. What if we did something like this?

  1. When MetricsEventSource needs to access the command handler it can use a property and implement the property like this:
privateCommandHandlerHandler{get{if(_handler==null){Interlocked.CompareExchange(ref_handler,newCommandHandler(this),null);}returnhandler;}
  1. When CommandHandler needs to access the MetricsEventSource it can do that through a property that was initialized in the CommandHandler constructor:
publicCommandHandler(MetricsEventSource parent){Parent=parent;}publicMetricsEventSourceParent{get;}// some code that needs to use parentParent.Error("Something bad happened");

@davmason

Copy link
Copy Markdown
Contributor

Works for me

@dramos020

dramos020 commented Oct 14, 2022

Copy link
Copy Markdown
ContributorAuthor

Just made the changes that were suggested. @noahfalk@davmason

@dramos020
dramos020 marked this pull request as ready for review October 14, 2022 21:16

@davmasondavmason left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@dramos020
dramos020 merged commit a32feb0 into dotnet:mainOct 20, 2022
@ghostghost locked as resolved and limited conversation to collaborators Nov 19, 2022
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.

dotnet-counters issue when monitoring a process launched via the same command-line

3 participants

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

Fixes issue when monitoring a process launched via the same command line - #76965

Merged
dramos020 merged 3 commits into
dotnet:mainfrom
dramos020:ProcessLaunchCountersBug
Oct 20, 2022
Merged

Fixes issue when monitoring a process launched via the same command line#76965
dramos020 merged 3 commits into
dotnet:mainfrom
dramos020:ProcessLaunchCountersBug

Conversation

@dramos020

@dramos020dramos020 commented Oct 12, 2022

Copy link
Copy Markdown
Contributor

Fixesdotnet/diagnostics#3366. A NullReferenceException was being thrown and caught because the CommandHandler in MetricsEventSource was being referenced before being initialized. Now custom metrics are displayed when trying to monitor a process in the same command line. Here is example output for a simple application with a custom meter that displays random values:

  • Running dotnet-counters monitor --counters System.Runtime,demo_meter -- countersbug.exe will now output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [System.Runtime]
    % Time in GC since last GC (%) 0
    Allocation Rate (B / 1 sec) 16,072
    CPU Usage (%) 0
    Exception Count (Count / 1 sec) 0
    GC Committed Bytes (MB) 0
    GC Fragmentation (%) 0
    GC Heap Size (MB) 0.462
    Gen 0 GC Count (Count / 1 sec) 0
    Gen 0 Size (B) 0
    Gen 1 GC Count (Count / 1 sec) 0
    Gen 1 Size (B) 0
    Gen 2 GC Count (Count / 1 sec) 0
    Gen 2 Size (B) 0
    IL Bytes Jitted (B) 47,239
    LOH Size (B) 0
    Monitor Lock Contention Count (Count / 1 sec) 0
    Number of Active Timers 0
    Number of Assemblies Loaded 13
    Number of Methods Jitted 438
    POH (Pinned Object Heap) Size (B) 0
    ThreadPool Completed Work Item Count (Count / 1 sec) 0
    ThreadPool Queue Length 0
    ThreadPool Thread Count 0
    Time spent in JIT (ms / 1 sec) 10.01
    Working Set (MB) 25.793
    [demo_meter]
    random (Count / 1 sec)
    instance=app -793.95
    
  • Running dotnet-counters monitor --counters demo_meter -- countersbug.exe will now output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [demo_meter]
    random (Count / 1 sec)
    instance=app 799.513
    

@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @tarekgh, @tommcdon, @pjanotti
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes dotnet/diagnostics#3366. A NullReferenceException was being thrown and caught because the CommandHandler in MetricsEventSource was being referenced before being initialized. Now custom metrics are displayed when trying to monitor a process in the same command line. Here is example output for a simple application with a custom meter that displays random values:

  • Running dotnet-counters monitor --counters System.Runtime,demo_meter -- countersbug.exe will output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [System.Runtime]
    % Time in GC since last GC (%) 0
    Allocation Rate (B / 1 sec) 16,072
    CPU Usage (%) 0
    Exception Count (Count / 1 sec) 0
    GC Committed Bytes (MB) 0
    GC Fragmentation (%) 0
    GC Heap Size (MB) 0.462
    Gen 0 GC Count (Count / 1 sec) 0
    Gen 0 Size (B) 0
    Gen 1 GC Count (Count / 1 sec) 0
    Gen 1 Size (B) 0
    Gen 2 GC Count (Count / 1 sec) 0
    Gen 2 Size (B) 0
    IL Bytes Jitted (B) 47,239
    LOH Size (B) 0
    Monitor Lock Contention Count (Count / 1 sec) 0
    Number of Active Timers 0
    Number of Assemblies Loaded 13
    Number of Methods Jitted 438
    POH (Pinned Object Heap) Size (B) 0
    ThreadPool Completed Work Item Count (Count / 1 sec) 0
    ThreadPool Queue Length 0
    ThreadPool Thread Count 0
    Time spent in JIT (ms / 1 sec) 10.01
    Working Set (MB) 25.793
    [demo_meter]
    random (Count / 1 sec)
    instance=app -793.95
    
  • Running dotnet-counters monitor --counters demo_meter -- countersbug.exe will output:

    Press p to pause, r to resume, q to quit.
    Status: Running
    [demo_meter]
    random (Count / 1 sec)
    instance=app 799.513
    
Author:dramos020
Assignees:-
Labels:

area-System.Diagnostics.Tracing

Milestone:-

@noahfalk

Copy link
Copy Markdown
Member

Can you include the callstack where the NullReferenceException occurs? A lot of the changes were swapping the Log property to a local parent field so does that also mean the static Log property was not initialized at that point? I want to understand what constraints we are working within :)

@davmason

davmason commented Oct 13, 2022

Copy link
Copy Markdown
Contributor

@noahfalk we're trying to grab the original exception but running in to technical difficulties.

The reason it fails is if you start a session before the runtime starts, you see the following scenario

  • MetricsEventSource static construct runs to initialize the Log object
  • It calls the base EventSource constructor, which sees a session is open and calls the OnEventCommand for MetricsEventSource from inside the EventSource constructor
  • Now we are calling in to MetricsEventSource before the static constructor has fully run and Log is assigned to so any call to Log will have a null reference

@noahfalk

Copy link
Copy Markdown
Member

Got it. What if we did something like this?

  1. When MetricsEventSource needs to access the command handler it can use a property and implement the property like this:
privateCommandHandlerHandler{get{if(_handler==null){Interlocked.CompareExchange(ref_handler,newCommandHandler(this),null);}returnhandler;}
  1. When CommandHandler needs to access the MetricsEventSource it can do that through a property that was initialized in the CommandHandler constructor:
publicCommandHandler(MetricsEventSource parent){Parent=parent;}publicMetricsEventSourceParent{get;}// some code that needs to use parentParent.Error("Something bad happened");

@davmason

Copy link
Copy Markdown
Contributor

Works for me

@dramos020

dramos020 commented Oct 14, 2022

Copy link
Copy Markdown
ContributorAuthor

Just made the changes that were suggested. @noahfalk@davmason

@dramos020
dramos020 marked this pull request as ready for review October 14, 2022 21:16

@davmasondavmason left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@dramos020
dramos020 merged commit a32feb0 into dotnet:mainOct 20, 2022
@ghostghost locked as resolved and limited conversation to collaborators Nov 19, 2022
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.

dotnet-counters issue when monitoring a process launched via the same command-line

3 participants

@dramos020@noahfalk@davmason