Fix locking around m_LoaderAllocatorReferences iteration - #68336

Merged
jkotas merged 2 commits into
dotnet:mainfrom
janvorli:fix-loaderallocatorreferences-iteration-lock
Apr 21, 2022
Merged

Fix locking around m_LoaderAllocatorReferences iteration#68336
jkotas merged 2 commits into
dotnet:mainfrom
janvorli:fix-loaderallocatorreferences-iteration-lock

Conversation

@janvorli

@janvorlijanvorli commented Apr 21, 2022

Copy link
Copy Markdown
Member

The iteration that marks loader allocators in LoaderAllocator::Mark()
was not being called under an appropriate lock, which lead to a rare and
hard to reproduce race condition and a crash in the
LoaderAllocator::Mark(). The issue happened when the
m_LoaderAllocatorReferences.Begin() returned an iterator at the time the
m_LoaderAllocatorReferences were empty and another thread has written
something into those references before the
m_LoaderAllocatorReferences.End() was called. The iter was then
evaluated as not equal to the End and the iter was getting dereferenced.
Since the iterator had m_table set to NULL, the dereferencing caused
crash.

The issue shows up as something like this:

Fatal error. Internal CLR error. (0x80131506)
at System.Reflection.LoaderAllocatorScout.<Destroy>g____PInvoke__|1_0(IntPtr)
at System.Reflection.LoaderAllocatorScout.Finalize()

The iteration that marks loader allocators in LoaderAllocator::Mark()
was not being called under an appropriate lock, which lead to a rare and
hard to reproduce race condition and a crash in the
LoaderAllocator::Mark(). The issue happened when the
m_LoaderAllocatorReferences.Begin() returned an iterator at the time the
m_LoaderAllocatorReferences were empty and another thread has written
something into those references before the
m_LoaderAllocatorReferences.End() was called. The iter was then
evaluated as not equal to the End and the iter was getting dereferenced.
Since the iterator had m_table set to NULL, the dereferencing caused
crash.
@janvorlijanvorli added this to the 6.0.x milestone Apr 21, 2022
@janvorlijanvorli self-assigned this Apr 21, 2022
// Iterate through every loader allocator, marking as we go
{
CrstHolder chLoaderAllocatorReferencesLock(pAppDomain->GetLoaderAllocatorReferencesLock());
CrstHolder chAssemblyListLock(pAppDomain->GetAssemblyListLock());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The second iteration below is going to acquire same locks now. We can acquire the locks just once for the whole duration of both iterations.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Makes sense, I'll update the PR that way.

@teo-tsirpanis

Copy link
Copy Markdown
Contributor

(setting the milestone to 7.0.0; the PR targets main, 6.0.x is for backports)

@teo-tsirpanisteo-tsirpanis modified the milestones: 6.0.x, 7.0.0Apr 21, 2022
@jkotas
jkotas merged commit 233c40e into dotnet:mainApr 21, 2022
@janvorli
janvorli deleted the fix-loaderallocatorreferences-iteration-lock branch April 28, 2022 13:18
janvorli added a commit to janvorli/runtime that referenced this pull request Apr 28, 2022
This change ports two unloadability fixes for issues found by a
customer.
* dotnet#68550 that adds reference between native
`LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of
them is used to resolve assembly using the other one. This reference
ensures that the one that provides the resolved `Assembly` isn't
collected before the one that uses it.
* dotnet#68336 that adds a missing lock around `m_LoaderAllocatorReferences`
iteration during assembly load context destruction.
carlossanlop pushed a commit that referenced this pull request May 5, 2022
* [Release/6.0] Port unloadability fixes
This change ports two unloadability fixes for issues found by a
customer.
* #68550 that adds reference between native
`LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of
them is used to resolve assembly using the other one. This reference
ensures that the one that provides the resolved `Assembly` isn't
collected before the one that uses it.
* #68336 that adds a missing lock around `m_LoaderAllocatorReferences`
iteration during assembly load context destruction.
* Remove breaking change part
The change in main has added an exception in case a collectible
`Assembly` is resolved into a non-collectible `AssemblyLoadContext`.
Although that is incorrect, there are cases when it would work. So the
added exception is a breaking change that I think we likely don't want
to get into 6.0
@ghostghost locked as resolved and limited conversation to collaborators May 28, 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.

3 participants

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

Fix locking around m_LoaderAllocatorReferences iteration - #68336

Merged
jkotas merged 2 commits into
dotnet:mainfrom
janvorli:fix-loaderallocatorreferences-iteration-lock
Apr 21, 2022
Merged

Fix locking around m_LoaderAllocatorReferences iteration#68336
jkotas merged 2 commits into
dotnet:mainfrom
janvorli:fix-loaderallocatorreferences-iteration-lock

Conversation

@janvorli

@janvorlijanvorli commented Apr 21, 2022

Copy link
Copy Markdown
Member

The iteration that marks loader allocators in LoaderAllocator::Mark()
was not being called under an appropriate lock, which lead to a rare and
hard to reproduce race condition and a crash in the
LoaderAllocator::Mark(). The issue happened when the
m_LoaderAllocatorReferences.Begin() returned an iterator at the time the
m_LoaderAllocatorReferences were empty and another thread has written
something into those references before the
m_LoaderAllocatorReferences.End() was called. The iter was then
evaluated as not equal to the End and the iter was getting dereferenced.
Since the iterator had m_table set to NULL, the dereferencing caused
crash.

The issue shows up as something like this:

Fatal error. Internal CLR error. (0x80131506)
at System.Reflection.LoaderAllocatorScout.<Destroy>g____PInvoke__|1_0(IntPtr)
at System.Reflection.LoaderAllocatorScout.Finalize()

The iteration that marks loader allocators in LoaderAllocator::Mark()
was not being called under an appropriate lock, which lead to a rare and
hard to reproduce race condition and a crash in the
LoaderAllocator::Mark(). The issue happened when the
m_LoaderAllocatorReferences.Begin() returned an iterator at the time the
m_LoaderAllocatorReferences were empty and another thread has written
something into those references before the
m_LoaderAllocatorReferences.End() was called. The iter was then
evaluated as not equal to the End and the iter was getting dereferenced.
Since the iterator had m_table set to NULL, the dereferencing caused
crash.
@janvorlijanvorli added this to the 6.0.x milestone Apr 21, 2022
@janvorlijanvorli self-assigned this Apr 21, 2022
// Iterate through every loader allocator, marking as we go
{
CrstHolder chLoaderAllocatorReferencesLock(pAppDomain->GetLoaderAllocatorReferencesLock());
CrstHolder chAssemblyListLock(pAppDomain->GetAssemblyListLock());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The second iteration below is going to acquire same locks now. We can acquire the locks just once for the whole duration of both iterations.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Makes sense, I'll update the PR that way.

@teo-tsirpanis

Copy link
Copy Markdown
Contributor

(setting the milestone to 7.0.0; the PR targets main, 6.0.x is for backports)

@teo-tsirpanisteo-tsirpanis modified the milestones: 6.0.x, 7.0.0Apr 21, 2022
@jkotas
jkotas merged commit 233c40e into dotnet:mainApr 21, 2022
@janvorli
janvorli deleted the fix-loaderallocatorreferences-iteration-lock branch April 28, 2022 13:18
janvorli added a commit to janvorli/runtime that referenced this pull request Apr 28, 2022
This change ports two unloadability fixes for issues found by a
customer.
* dotnet#68550 that adds reference between native
`LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of
them is used to resolve assembly using the other one. This reference
ensures that the one that provides the resolved `Assembly` isn't
collected before the one that uses it.
* dotnet#68336 that adds a missing lock around `m_LoaderAllocatorReferences`
iteration during assembly load context destruction.
carlossanlop pushed a commit that referenced this pull request May 5, 2022
* [Release/6.0] Port unloadability fixes
This change ports two unloadability fixes for issues found by a
customer.
* #68550 that adds reference between native
`LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of
them is used to resolve assembly using the other one. This reference
ensures that the one that provides the resolved `Assembly` isn't
collected before the one that uses it.
* #68336 that adds a missing lock around `m_LoaderAllocatorReferences`
iteration during assembly load context destruction.
* Remove breaking change part
The change in main has added an exception in case a collectible
`Assembly` is resolved into a non-collectible `AssemblyLoadContext`.
Although that is incorrect, there are cases when it would work. So the
added exception is a breaking change that I think we likely don't want
to get into 6.0
@ghostghost locked as resolved and limited conversation to collaborators May 28, 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.

3 participants

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

Fix locking around m_LoaderAllocatorReferences iteration - #68336

Merged
jkotas merged 2 commits into
dotnet:mainfrom
janvorli:fix-loaderallocatorreferences-iteration-lock
Apr 21, 2022
Merged

Fix locking around m_LoaderAllocatorReferences iteration#68336
jkotas merged 2 commits into
dotnet:mainfrom
janvorli:fix-loaderallocatorreferences-iteration-lock

Conversation

@janvorli

@janvorlijanvorli commented Apr 21, 2022

Copy link
Copy Markdown
Member

The iteration that marks loader allocators in LoaderAllocator::Mark()
was not being called under an appropriate lock, which lead to a rare and
hard to reproduce race condition and a crash in the
LoaderAllocator::Mark(). The issue happened when the
m_LoaderAllocatorReferences.Begin() returned an iterator at the time the
m_LoaderAllocatorReferences were empty and another thread has written
something into those references before the
m_LoaderAllocatorReferences.End() was called. The iter was then
evaluated as not equal to the End and the iter was getting dereferenced.
Since the iterator had m_table set to NULL, the dereferencing caused
crash.

The issue shows up as something like this:

Fatal error. Internal CLR error. (0x80131506)
at System.Reflection.LoaderAllocatorScout.<Destroy>g____PInvoke__|1_0(IntPtr)
at System.Reflection.LoaderAllocatorScout.Finalize()

The iteration that marks loader allocators in LoaderAllocator::Mark()
was not being called under an appropriate lock, which lead to a rare and
hard to reproduce race condition and a crash in the
LoaderAllocator::Mark(). The issue happened when the
m_LoaderAllocatorReferences.Begin() returned an iterator at the time the
m_LoaderAllocatorReferences were empty and another thread has written
something into those references before the
m_LoaderAllocatorReferences.End() was called. The iter was then
evaluated as not equal to the End and the iter was getting dereferenced.
Since the iterator had m_table set to NULL, the dereferencing caused
crash.
@janvorlijanvorli added this to the 6.0.x milestone Apr 21, 2022
@janvorlijanvorli self-assigned this Apr 21, 2022
// Iterate through every loader allocator, marking as we go
{
CrstHolder chLoaderAllocatorReferencesLock(pAppDomain->GetLoaderAllocatorReferencesLock());
CrstHolder chAssemblyListLock(pAppDomain->GetAssemblyListLock());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The second iteration below is going to acquire same locks now. We can acquire the locks just once for the whole duration of both iterations.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Makes sense, I'll update the PR that way.

@teo-tsirpanis

Copy link
Copy Markdown
Contributor

(setting the milestone to 7.0.0; the PR targets main, 6.0.x is for backports)

@teo-tsirpanisteo-tsirpanis modified the milestones: 6.0.x, 7.0.0Apr 21, 2022
@jkotas
jkotas merged commit 233c40e into dotnet:mainApr 21, 2022
@janvorli
janvorli deleted the fix-loaderallocatorreferences-iteration-lock branch April 28, 2022 13:18
janvorli added a commit to janvorli/runtime that referenced this pull request Apr 28, 2022
This change ports two unloadability fixes for issues found by a
customer.
* dotnet#68550 that adds reference between native
`LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of
them is used to resolve assembly using the other one. This reference
ensures that the one that provides the resolved `Assembly` isn't
collected before the one that uses it.
* dotnet#68336 that adds a missing lock around `m_LoaderAllocatorReferences`
iteration during assembly load context destruction.
carlossanlop pushed a commit that referenced this pull request May 5, 2022
* [Release/6.0] Port unloadability fixes
This change ports two unloadability fixes for issues found by a
customer.
* #68550 that adds reference between native
`LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of
them is used to resolve assembly using the other one. This reference
ensures that the one that provides the resolved `Assembly` isn't
collected before the one that uses it.
* #68336 that adds a missing lock around `m_LoaderAllocatorReferences`
iteration during assembly load context destruction.
* Remove breaking change part
The change in main has added an exception in case a collectible
`Assembly` is resolved into a non-collectible `AssemblyLoadContext`.
Although that is incorrect, there are cases when it would work. So the
added exception is a breaking change that I think we likely don't want
to get into 6.0
@ghostghost locked as resolved and limited conversation to collaborators May 28, 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.

3 participants

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

Fix locking around m_LoaderAllocatorReferences iteration - #68336

Merged
jkotas merged 2 commits into
dotnet:mainfrom
janvorli:fix-loaderallocatorreferences-iteration-lock
Apr 21, 2022
Merged

Fix locking around m_LoaderAllocatorReferences iteration#68336
jkotas merged 2 commits into
dotnet:mainfrom
janvorli:fix-loaderallocatorreferences-iteration-lock

Conversation

@janvorli

@janvorlijanvorli commented Apr 21, 2022

Copy link
Copy Markdown
Member

The iteration that marks loader allocators in LoaderAllocator::Mark()
was not being called under an appropriate lock, which lead to a rare and
hard to reproduce race condition and a crash in the
LoaderAllocator::Mark(). The issue happened when the
m_LoaderAllocatorReferences.Begin() returned an iterator at the time the
m_LoaderAllocatorReferences were empty and another thread has written
something into those references before the
m_LoaderAllocatorReferences.End() was called. The iter was then
evaluated as not equal to the End and the iter was getting dereferenced.
Since the iterator had m_table set to NULL, the dereferencing caused
crash.

The issue shows up as something like this:

Fatal error. Internal CLR error. (0x80131506)
at System.Reflection.LoaderAllocatorScout.<Destroy>g____PInvoke__|1_0(IntPtr)
at System.Reflection.LoaderAllocatorScout.Finalize()

The iteration that marks loader allocators in LoaderAllocator::Mark()
was not being called under an appropriate lock, which lead to a rare and
hard to reproduce race condition and a crash in the
LoaderAllocator::Mark(). The issue happened when the
m_LoaderAllocatorReferences.Begin() returned an iterator at the time the
m_LoaderAllocatorReferences were empty and another thread has written
something into those references before the
m_LoaderAllocatorReferences.End() was called. The iter was then
evaluated as not equal to the End and the iter was getting dereferenced.
Since the iterator had m_table set to NULL, the dereferencing caused
crash.
@janvorlijanvorli added this to the 6.0.x milestone Apr 21, 2022
@janvorlijanvorli self-assigned this Apr 21, 2022
// Iterate through every loader allocator, marking as we go
{
CrstHolder chLoaderAllocatorReferencesLock(pAppDomain->GetLoaderAllocatorReferencesLock());
CrstHolder chAssemblyListLock(pAppDomain->GetAssemblyListLock());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The second iteration below is going to acquire same locks now. We can acquire the locks just once for the whole duration of both iterations.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Makes sense, I'll update the PR that way.

@teo-tsirpanis

Copy link
Copy Markdown
Contributor

(setting the milestone to 7.0.0; the PR targets main, 6.0.x is for backports)

@teo-tsirpanisteo-tsirpanis modified the milestones: 6.0.x, 7.0.0Apr 21, 2022
@jkotas
jkotas merged commit 233c40e into dotnet:mainApr 21, 2022
@janvorli
janvorli deleted the fix-loaderallocatorreferences-iteration-lock branch April 28, 2022 13:18
janvorli added a commit to janvorli/runtime that referenced this pull request Apr 28, 2022
This change ports two unloadability fixes for issues found by a
customer.
* dotnet#68550 that adds reference between native
`LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of
them is used to resolve assembly using the other one. This reference
ensures that the one that provides the resolved `Assembly` isn't
collected before the one that uses it.
* dotnet#68336 that adds a missing lock around `m_LoaderAllocatorReferences`
iteration during assembly load context destruction.
carlossanlop pushed a commit that referenced this pull request May 5, 2022
* [Release/6.0] Port unloadability fixes
This change ports two unloadability fixes for issues found by a
customer.
* #68550 that adds reference between native
`LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of
them is used to resolve assembly using the other one. This reference
ensures that the one that provides the resolved `Assembly` isn't
collected before the one that uses it.
* #68336 that adds a missing lock around `m_LoaderAllocatorReferences`
iteration during assembly load context destruction.
* Remove breaking change part
The change in main has added an exception in case a collectible
`Assembly` is resolved into a non-collectible `AssemblyLoadContext`.
Although that is incorrect, there are cases when it would work. So the
added exception is a breaking change that I think we likely don't want
to get into 6.0
@ghostghost locked as resolved and limited conversation to collaborators May 28, 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.

3 participants

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

Fix locking around m_LoaderAllocatorReferences iteration - #68336

Merged
jkotas merged 2 commits into
dotnet:mainfrom
janvorli:fix-loaderallocatorreferences-iteration-lock
Apr 21, 2022
Merged

Fix locking around m_LoaderAllocatorReferences iteration#68336
jkotas merged 2 commits into
dotnet:mainfrom
janvorli:fix-loaderallocatorreferences-iteration-lock

Conversation

@janvorli

@janvorlijanvorli commented Apr 21, 2022

Copy link
Copy Markdown
Member

The iteration that marks loader allocators in LoaderAllocator::Mark()
was not being called under an appropriate lock, which lead to a rare and
hard to reproduce race condition and a crash in the
LoaderAllocator::Mark(). The issue happened when the
m_LoaderAllocatorReferences.Begin() returned an iterator at the time the
m_LoaderAllocatorReferences were empty and another thread has written
something into those references before the
m_LoaderAllocatorReferences.End() was called. The iter was then
evaluated as not equal to the End and the iter was getting dereferenced.
Since the iterator had m_table set to NULL, the dereferencing caused
crash.

The issue shows up as something like this:

Fatal error. Internal CLR error. (0x80131506)
at System.Reflection.LoaderAllocatorScout.<Destroy>g____PInvoke__|1_0(IntPtr)
at System.Reflection.LoaderAllocatorScout.Finalize()

The iteration that marks loader allocators in LoaderAllocator::Mark()
was not being called under an appropriate lock, which lead to a rare and
hard to reproduce race condition and a crash in the
LoaderAllocator::Mark(). The issue happened when the
m_LoaderAllocatorReferences.Begin() returned an iterator at the time the
m_LoaderAllocatorReferences were empty and another thread has written
something into those references before the
m_LoaderAllocatorReferences.End() was called. The iter was then
evaluated as not equal to the End and the iter was getting dereferenced.
Since the iterator had m_table set to NULL, the dereferencing caused
crash.
@janvorlijanvorli added this to the 6.0.x milestone Apr 21, 2022
@janvorlijanvorli self-assigned this Apr 21, 2022
// Iterate through every loader allocator, marking as we go
{
CrstHolder chLoaderAllocatorReferencesLock(pAppDomain->GetLoaderAllocatorReferencesLock());
CrstHolder chAssemblyListLock(pAppDomain->GetAssemblyListLock());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The second iteration below is going to acquire same locks now. We can acquire the locks just once for the whole duration of both iterations.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Makes sense, I'll update the PR that way.

@teo-tsirpanis

Copy link
Copy Markdown
Contributor

(setting the milestone to 7.0.0; the PR targets main, 6.0.x is for backports)

@teo-tsirpanisteo-tsirpanis modified the milestones: 6.0.x, 7.0.0Apr 21, 2022
@jkotas
jkotas merged commit 233c40e into dotnet:mainApr 21, 2022
@janvorli
janvorli deleted the fix-loaderallocatorreferences-iteration-lock branch April 28, 2022 13:18
janvorli added a commit to janvorli/runtime that referenced this pull request Apr 28, 2022
This change ports two unloadability fixes for issues found by a
customer.
* dotnet#68550 that adds reference between native
`LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of
them is used to resolve assembly using the other one. This reference
ensures that the one that provides the resolved `Assembly` isn't
collected before the one that uses it.
* dotnet#68336 that adds a missing lock around `m_LoaderAllocatorReferences`
iteration during assembly load context destruction.
carlossanlop pushed a commit that referenced this pull request May 5, 2022
* [Release/6.0] Port unloadability fixes
This change ports two unloadability fixes for issues found by a
customer.
* #68550 that adds reference between native
`LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of
them is used to resolve assembly using the other one. This reference
ensures that the one that provides the resolved `Assembly` isn't
collected before the one that uses it.
* #68336 that adds a missing lock around `m_LoaderAllocatorReferences`
iteration during assembly load context destruction.
* Remove breaking change part
The change in main has added an exception in case a collectible
`Assembly` is resolved into a non-collectible `AssemblyLoadContext`.
Although that is incorrect, there are cases when it would work. So the
added exception is a breaking change that I think we likely don't want
to get into 6.0
@ghostghost locked as resolved and limited conversation to collaborators May 28, 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.

3 participants

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

Fix locking around m_LoaderAllocatorReferences iteration - #68336

Merged
jkotas merged 2 commits into
dotnet:mainfrom
janvorli:fix-loaderallocatorreferences-iteration-lock
Apr 21, 2022
Merged

Fix locking around m_LoaderAllocatorReferences iteration#68336
jkotas merged 2 commits into
dotnet:mainfrom
janvorli:fix-loaderallocatorreferences-iteration-lock

Conversation

@janvorli

@janvorlijanvorli commented Apr 21, 2022

Copy link
Copy Markdown
Member

The iteration that marks loader allocators in LoaderAllocator::Mark()
was not being called under an appropriate lock, which lead to a rare and
hard to reproduce race condition and a crash in the
LoaderAllocator::Mark(). The issue happened when the
m_LoaderAllocatorReferences.Begin() returned an iterator at the time the
m_LoaderAllocatorReferences were empty and another thread has written
something into those references before the
m_LoaderAllocatorReferences.End() was called. The iter was then
evaluated as not equal to the End and the iter was getting dereferenced.
Since the iterator had m_table set to NULL, the dereferencing caused
crash.

The issue shows up as something like this:

Fatal error. Internal CLR error. (0x80131506)
at System.Reflection.LoaderAllocatorScout.<Destroy>g____PInvoke__|1_0(IntPtr)
at System.Reflection.LoaderAllocatorScout.Finalize()

The iteration that marks loader allocators in LoaderAllocator::Mark()
was not being called under an appropriate lock, which lead to a rare and
hard to reproduce race condition and a crash in the
LoaderAllocator::Mark(). The issue happened when the
m_LoaderAllocatorReferences.Begin() returned an iterator at the time the
m_LoaderAllocatorReferences were empty and another thread has written
something into those references before the
m_LoaderAllocatorReferences.End() was called. The iter was then
evaluated as not equal to the End and the iter was getting dereferenced.
Since the iterator had m_table set to NULL, the dereferencing caused
crash.
@janvorlijanvorli added this to the 6.0.x milestone Apr 21, 2022
@janvorlijanvorli self-assigned this Apr 21, 2022
// Iterate through every loader allocator, marking as we go
{
CrstHolder chLoaderAllocatorReferencesLock(pAppDomain->GetLoaderAllocatorReferencesLock());
CrstHolder chAssemblyListLock(pAppDomain->GetAssemblyListLock());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The second iteration below is going to acquire same locks now. We can acquire the locks just once for the whole duration of both iterations.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Makes sense, I'll update the PR that way.

@teo-tsirpanis

Copy link
Copy Markdown
Contributor

(setting the milestone to 7.0.0; the PR targets main, 6.0.x is for backports)

@teo-tsirpanisteo-tsirpanis modified the milestones: 6.0.x, 7.0.0Apr 21, 2022
@jkotas
jkotas merged commit 233c40e into dotnet:mainApr 21, 2022
@janvorli
janvorli deleted the fix-loaderallocatorreferences-iteration-lock branch April 28, 2022 13:18
janvorli added a commit to janvorli/runtime that referenced this pull request Apr 28, 2022
This change ports two unloadability fixes for issues found by a
customer.
* dotnet#68550 that adds reference between native
`LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of
them is used to resolve assembly using the other one. This reference
ensures that the one that provides the resolved `Assembly` isn't
collected before the one that uses it.
* dotnet#68336 that adds a missing lock around `m_LoaderAllocatorReferences`
iteration during assembly load context destruction.
carlossanlop pushed a commit that referenced this pull request May 5, 2022
* [Release/6.0] Port unloadability fixes
This change ports two unloadability fixes for issues found by a
customer.
* #68550 that adds reference between native
`LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of
them is used to resolve assembly using the other one. This reference
ensures that the one that provides the resolved `Assembly` isn't
collected before the one that uses it.
* #68336 that adds a missing lock around `m_LoaderAllocatorReferences`
iteration during assembly load context destruction.
* Remove breaking change part
The change in main has added an exception in case a collectible
`Assembly` is resolved into a non-collectible `AssemblyLoadContext`.
Although that is incorrect, there are cases when it would work. So the
added exception is a breaking change that I think we likely don't want
to get into 6.0
@ghostghost locked as resolved and limited conversation to collaborators May 28, 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.

3 participants

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

Fix locking around m_LoaderAllocatorReferences iteration - #68336

Merged
jkotas merged 2 commits into
dotnet:mainfrom
janvorli:fix-loaderallocatorreferences-iteration-lock
Apr 21, 2022
Merged

Fix locking around m_LoaderAllocatorReferences iteration#68336
jkotas merged 2 commits into
dotnet:mainfrom
janvorli:fix-loaderallocatorreferences-iteration-lock

Conversation

@janvorli

@janvorlijanvorli commented Apr 21, 2022

Copy link
Copy Markdown
Member

The iteration that marks loader allocators in LoaderAllocator::Mark()
was not being called under an appropriate lock, which lead to a rare and
hard to reproduce race condition and a crash in the
LoaderAllocator::Mark(). The issue happened when the
m_LoaderAllocatorReferences.Begin() returned an iterator at the time the
m_LoaderAllocatorReferences were empty and another thread has written
something into those references before the
m_LoaderAllocatorReferences.End() was called. The iter was then
evaluated as not equal to the End and the iter was getting dereferenced.
Since the iterator had m_table set to NULL, the dereferencing caused
crash.

The issue shows up as something like this:

Fatal error. Internal CLR error. (0x80131506)
at System.Reflection.LoaderAllocatorScout.<Destroy>g____PInvoke__|1_0(IntPtr)
at System.Reflection.LoaderAllocatorScout.Finalize()

The iteration that marks loader allocators in LoaderAllocator::Mark()
was not being called under an appropriate lock, which lead to a rare and
hard to reproduce race condition and a crash in the
LoaderAllocator::Mark(). The issue happened when the
m_LoaderAllocatorReferences.Begin() returned an iterator at the time the
m_LoaderAllocatorReferences were empty and another thread has written
something into those references before the
m_LoaderAllocatorReferences.End() was called. The iter was then
evaluated as not equal to the End and the iter was getting dereferenced.
Since the iterator had m_table set to NULL, the dereferencing caused
crash.
@janvorlijanvorli added this to the 6.0.x milestone Apr 21, 2022
@janvorlijanvorli self-assigned this Apr 21, 2022
// Iterate through every loader allocator, marking as we go
{
CrstHolder chLoaderAllocatorReferencesLock(pAppDomain->GetLoaderAllocatorReferencesLock());
CrstHolder chAssemblyListLock(pAppDomain->GetAssemblyListLock());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The second iteration below is going to acquire same locks now. We can acquire the locks just once for the whole duration of both iterations.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Makes sense, I'll update the PR that way.

@teo-tsirpanis

Copy link
Copy Markdown
Contributor

(setting the milestone to 7.0.0; the PR targets main, 6.0.x is for backports)

@teo-tsirpanisteo-tsirpanis modified the milestones: 6.0.x, 7.0.0Apr 21, 2022
@jkotas
jkotas merged commit 233c40e into dotnet:mainApr 21, 2022
@janvorli
janvorli deleted the fix-loaderallocatorreferences-iteration-lock branch April 28, 2022 13:18
janvorli added a commit to janvorli/runtime that referenced this pull request Apr 28, 2022
This change ports two unloadability fixes for issues found by a
customer.
* dotnet#68550 that adds reference between native
`LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of
them is used to resolve assembly using the other one. This reference
ensures that the one that provides the resolved `Assembly` isn't
collected before the one that uses it.
* dotnet#68336 that adds a missing lock around `m_LoaderAllocatorReferences`
iteration during assembly load context destruction.
carlossanlop pushed a commit that referenced this pull request May 5, 2022
* [Release/6.0] Port unloadability fixes
This change ports two unloadability fixes for issues found by a
customer.
* #68550 that adds reference between native
`LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of
them is used to resolve assembly using the other one. This reference
ensures that the one that provides the resolved `Assembly` isn't
collected before the one that uses it.
* #68336 that adds a missing lock around `m_LoaderAllocatorReferences`
iteration during assembly load context destruction.
* Remove breaking change part
The change in main has added an exception in case a collectible
`Assembly` is resolved into a non-collectible `AssemblyLoadContext`.
Although that is incorrect, there are cases when it would work. So the
added exception is a breaking change that I think we likely don't want
to get into 6.0
@ghostghost locked as resolved and limited conversation to collaborators May 28, 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.

3 participants

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

Fix locking around m_LoaderAllocatorReferences iteration - #68336

Merged
jkotas merged 2 commits into
dotnet:mainfrom
janvorli:fix-loaderallocatorreferences-iteration-lock
Apr 21, 2022
Merged

Fix locking around m_LoaderAllocatorReferences iteration#68336
jkotas merged 2 commits into
dotnet:mainfrom
janvorli:fix-loaderallocatorreferences-iteration-lock

Conversation

@janvorli

@janvorlijanvorli commented Apr 21, 2022

Copy link
Copy Markdown
Member

The iteration that marks loader allocators in LoaderAllocator::Mark()
was not being called under an appropriate lock, which lead to a rare and
hard to reproduce race condition and a crash in the
LoaderAllocator::Mark(). The issue happened when the
m_LoaderAllocatorReferences.Begin() returned an iterator at the time the
m_LoaderAllocatorReferences were empty and another thread has written
something into those references before the
m_LoaderAllocatorReferences.End() was called. The iter was then
evaluated as not equal to the End and the iter was getting dereferenced.
Since the iterator had m_table set to NULL, the dereferencing caused
crash.

The issue shows up as something like this:

Fatal error. Internal CLR error. (0x80131506)
at System.Reflection.LoaderAllocatorScout.<Destroy>g____PInvoke__|1_0(IntPtr)
at System.Reflection.LoaderAllocatorScout.Finalize()

The iteration that marks loader allocators in LoaderAllocator::Mark()
was not being called under an appropriate lock, which lead to a rare and
hard to reproduce race condition and a crash in the
LoaderAllocator::Mark(). The issue happened when the
m_LoaderAllocatorReferences.Begin() returned an iterator at the time the
m_LoaderAllocatorReferences were empty and another thread has written
something into those references before the
m_LoaderAllocatorReferences.End() was called. The iter was then
evaluated as not equal to the End and the iter was getting dereferenced.
Since the iterator had m_table set to NULL, the dereferencing caused
crash.
@janvorlijanvorli added this to the 6.0.x milestone Apr 21, 2022
@janvorlijanvorli self-assigned this Apr 21, 2022
// Iterate through every loader allocator, marking as we go
{
CrstHolder chLoaderAllocatorReferencesLock(pAppDomain->GetLoaderAllocatorReferencesLock());
CrstHolder chAssemblyListLock(pAppDomain->GetAssemblyListLock());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The second iteration below is going to acquire same locks now. We can acquire the locks just once for the whole duration of both iterations.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Makes sense, I'll update the PR that way.

@teo-tsirpanis

Copy link
Copy Markdown
Contributor

(setting the milestone to 7.0.0; the PR targets main, 6.0.x is for backports)

@teo-tsirpanisteo-tsirpanis modified the milestones: 6.0.x, 7.0.0Apr 21, 2022
@jkotas
jkotas merged commit 233c40e into dotnet:mainApr 21, 2022
@janvorli
janvorli deleted the fix-loaderallocatorreferences-iteration-lock branch April 28, 2022 13:18
janvorli added a commit to janvorli/runtime that referenced this pull request Apr 28, 2022
This change ports two unloadability fixes for issues found by a
customer.
* dotnet#68550 that adds reference between native
`LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of
them is used to resolve assembly using the other one. This reference
ensures that the one that provides the resolved `Assembly` isn't
collected before the one that uses it.
* dotnet#68336 that adds a missing lock around `m_LoaderAllocatorReferences`
iteration during assembly load context destruction.
carlossanlop pushed a commit that referenced this pull request May 5, 2022
* [Release/6.0] Port unloadability fixes
This change ports two unloadability fixes for issues found by a
customer.
* #68550 that adds reference between native
`LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of
them is used to resolve assembly using the other one. This reference
ensures that the one that provides the resolved `Assembly` isn't
collected before the one that uses it.
* #68336 that adds a missing lock around `m_LoaderAllocatorReferences`
iteration during assembly load context destruction.
* Remove breaking change part
The change in main has added an exception in case a collectible
`Assembly` is resolved into a non-collectible `AssemblyLoadContext`.
Although that is incorrect, there are cases when it would work. So the
added exception is a breaking change that I think we likely don't want
to get into 6.0
@ghostghost locked as resolved and limited conversation to collaborators May 28, 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.

3 participants

@janvorli@teo-tsirpanis@jkotas