Collections XML docs migration and runnable code samples#1
Open
richlander wants to merge 7 commits intomainfrom
Open
Collections XML docs migration and runnable code samples#1richlander wants to merge 7 commits intomainfrom
richlander wants to merge 7 commits intomainfrom
Conversation
Set up samples infrastructure for the collections XML doc migration pilot. Targets 16 core collection types across System.Private.CoreLib and System.Collections (562 members total, all Good quality, zero samples currently). Types: List, Dictionary, HashSet, Queue, Stack, SortedSet, SortedDictionary, SortedList, LinkedList, LinkedListNode, OrderedDictionary, PriorityQueue, SynchronizedCollection, SynchronizedReadOnlyCollection, SynchronizedKeyedCollection, KeyedByTypeCollection. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
First batch of the collections pilot. Each type gets: - A runnable .Examples.cs with self-contained local functions - A .samples.json fragment mapping DocIds to methods - Entries merged into the main samples.json (107 total) List<T>: 9 functions, 55 DocId mappings Dictionary<TKey,TValue>: 5 functions, 19 DocId mappings HashSet<T>: 4 functions, 17 DocId mappings Queue<T>: 3 functions, 16 DocId mappings Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Second batch of the collections pilot. Each type gets a runnable .Examples.cs with self-contained local functions and a .samples.json fragment merged into the main samples.json (108 entries). Stack<T>: 10 functions, 24 DocId mappings LinkedList<T> + LinkedListNode<T>: 5 functions, 31 DocId mappings SortedSet<T>: 7 functions, 29 DocId mappings PriorityQueue<TElement,TPriority>: 4 functions, 24 DocId mappings Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Final batch of the collections pilot. Each type gets a runnable .Examples.cs with self-contained local functions and a .samples.json fragment. System.Collections samples.json now has 245 entries. SortedDictionary<TKey,TValue>: 5 functions, 40 DocId mappings SortedList<TKey,TValue>: 6 functions, 27 DocId mappings OrderedDictionary<TKey,TValue>: 7 functions, 70 DocId mappings Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Introduces a shell script that finds all *.Examples.cs files under src/libraries/*/samples/, runs each with 'dotnet run', and reports a pass/fail summary. Failures show full output for diagnosis. Usage: ./eng/run-samples.sh # run all, report failures ./eng/run-samples.sh --verbose # run all, show all output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
….json Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Covers: overview and slash toolkit link, design goals (any-scope, repeatable, fleet-built), per-type coverage table, source fidelity, branch history, sample runner details and ideal CI integration path, Directory.Build.props isolation tradeoff, and sample prioritization as an open constraint. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
richlander
pushed a commit
that referenced
this pull request
Feb 20, 2026
…er (dotnet#123735) From discussion, opting into enabling the crash chaining is more correct. <s>The previously registered signal action/handler aren't guaranteed to return, so we lose out on notifying shutdown and creating a dump in those cases. Specifically, PROCCreateCrashDumpIfEnabled would be the last chance to provide the managed context for the thread that crashed. e.g. On Android CoreCLR, it seems that, by default, signal handlers are already registered by Android's runtime (/apex/com.android.runtime/bin/linker64 + /system/lib64/libandroid_runtime.so). Whenever an unhandled synchronous fault occurs, the previously registered handler will not return back to invoke_previous_action and aborts the thread itself, so PROCCreateCrashDumpIfEnabled will not be hit.</s> ## Sigsegv behavior Android CoreCLR vs other platforms ### Android CoreCLR When intentionally writing to NULL (sigsegv) on Android CoreCLR, the previously registered signal handler goes down this path https://github.com/dotnet/runtime/blob/40e8c73b8f3b5f478a9bf03cf55c71d0608a8855/src/coreclr/pal/src/exception/signal.cpp#L454, and the thread aborts before hitting PROCNotifyProcessShutdown and PROCCreateCrashDumpIfEnabled. ### MacOS/Linux/NativeAOT(linux) On MacOS, Linux, NativeAOT (Only checked linux at time of writing), the same intentional SIGSEGV will hit https://github.com/dotnet/runtime/blob/40e8c73b8f3b5f478a9bf03cf55c71d0608a8855/src/coreclr/pal/src/exception/signal.cpp#L431-L448 instead because there is no previously registered signal handler. In those cases, PROCCreateCrashDumpIfEnabled is hit and managed callstacks are captured in the dump. ## History investigation From a github history dive, I didn't spot anything in particular requiring the previous signal handler to be invoked before PROCNotifyProcessShutdown + PROCCreateCrashDumpIfEnabled. PROCNotifyProcessShutdown was first introduced in dotnet@1433c3f. It doesn't seem to state a particular reason for invoking it after the previous signal handler. PROCCreateCrashDumpIfEnabled was added to signal.cpp in dotnet@7f9bd2c because the PROCNotifyProcessShutdown didn't create a crash dump. It doesn't state any particular reason for being invoked after the previously registered signal handler, and was probably just placed next to PROCNotifyProcessShutdown. `invoke_previous_action` was introduced in dotnet@a740f65 and was refactoring while maintaining the order. ## Android CoreCLR behavior after swapping order Locally, I have POC changes to emit managed callstacks in Android's PROCCreateCrashDumpIfEnabled. ``` 01-28 17:26:40.951 2416 2440 F DOTNET : Native crash detected; attempting managed stack trace. 01-28 17:26:40.951 2416 2440 F DOTNET : {"stack":[ 01-28 17:26:40.951 2416 2440 F DOTNET : {"ip":"0x0","module":"0x0","offset":"0x0","name":"Program.MemSet(Void*, Int32, UIntPtr)"}, 01-28 17:26:40.951 2416 2440 F DOTNET : {"ip":"0x78d981145973","module":"0x0","offset":"0x0","name":"Program.MemSet(Void*, Int32, UIntPtr)"}, 01-28 17:26:40.951 2416 2440 F DOTNET : {"ip":"0x78d981145973","module":"0x0","offset":"0x73","name":"Program.ForceNativeSegv()"}, 01-28 17:26:40.951 2416 2440 F DOTNET : {"ip":"0x78d981141b60","module":"0x0","offset":"0x70","name":"Program.Main(System.String[])"} 01-28 17:26:40.951 2416 2440 F DOTNET : ]} 01-28 17:26:40.952 2416 2440 F DOTNET : Crash dump hook completed. --------- beginning of crash 01-28 17:26:40.952 2416 2440 F libc : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 2440 (.dot.MonoRunner), pid 2416 (ulator.JIT.Test) ..... 01-28 17:26:46.882 2921 2921 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 01-28 17:26:46.882 2921 2921 F DEBUG : Build fingerprint: 'google/sdk_gphone64_x86_64/emu64xa:16/BE2A.250530.026.D1/13818094:user/release-keys' 01-28 17:26:46.882 2921 2921 F DEBUG : Revision: '0' 01-28 17:26:46.882 2921 2921 F DEBUG : ABI: 'x86_64' 01-28 17:26:46.882 2921 2921 F DEBUG : Timestamp: 2026-01-28 17:26:41.492831700-0500 01-28 17:26:46.882 2921 2921 F DEBUG : Process uptime: 20s 01-28 17:26:46.883 2921 2921 F DEBUG : Cmdline: net.dot.Android.Device_Emulator.JIT.Test 01-28 17:26:46.883 2921 2921 F DEBUG : pid: 2416, tid: 2440, name: .dot.MonoRunner >>> net.dot.Android.Device_Emulator.JIT.Test <<< 01-28 17:26:46.883 2921 2921 F DEBUG : uid: 10219 01-28 17:26:46.883 2921 2921 F DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0000000000000000 01-28 17:26:46.883 2921 2921 F DEBUG : Cause: null pointer dereference 01-28 17:26:46.883 2921 2921 F DEBUG : Abort message: 'CoreCLR: previous handler for ' 01-28 17:26:46.883 2921 2921 F DEBUG : rax 0000000000000000 rbx 000078da87ffade0 rcx 0000000000000000 rdx 0000000000000001 01-28 17:26:46.884 1237 1297 I s.nexuslauncher: AssetManager2(0x78dd08cd9178) locale list changing from [] to [en-US] 01-28 17:26:46.903 2447 2594 I BugleNotifications: Creating notification input ids [CONTEXT im_entry_input="" im_notification_input="" im_settings_store_input="" im_final_input="" ] 01-28 17:26:46.905 2921 2921 F DEBUG : r8 00007ffcde5a8080 r9 34d9bb0e67871eb0 r10 000078ddb4111870 r11 0000000000000293 01-28 17:26:46.906 2921 2921 F DEBUG : r12 0000000000000001 r13 000078da87ffafa0 r14 0000000000000000 r15 000078da87ffaf18 01-28 17:26:46.906 2921 2921 F DEBUG : rdi 0000000000000000 rsi 0000000000000000 01-28 17:26:46.906 2921 2921 F DEBUG : rbp 000078da87ffac40 rsp 000078da87ffabc8 rip 000078ddb41118a2 01-28 17:26:46.906 2921 2921 F DEBUG : 2 total frames 01-28 17:26:46.906 2921 2921 F DEBUG : backtrace: 01-28 17:26:46.906 2921 2921 F DEBUG : #00 pc 000000000008f8a2 /apex/com.android.runtime/lib64/bionic/libc.so (memset_avx2+50) (BuildId: fcb82240218d1473de1e3d2137c0be35) 01-28 17:26:46.906 2921 2921 F DEBUG : #1 pc 0000000000049972 /memfd:doublemapper (deleted) (offset 0x111000) ``` Now theres a window to log managed callstacks before the original signal handler aborts and triggers a tombstone. ## Android Mono behavior Mono provides two embeddings APIs to configure signal and crash chaining https://github.com/dotnet/runtime/blob/61d3943de41e948bb0ecf871b92eb456d2dd74d8/src/mono/mono/mini/driver.c#L2864-L2894 that determine whether synchronous faults would chain https://github.com/dotnet/runtime/blob/61d3943de41e948bb0ecf871b92eb456d2dd74d8/src/mono/mono/mini/mini-runtime.c#L3892-L3903 They would only chain to the previous signal handler https://github.com/dotnet/runtime/blob/61d3943de41e948bb0ecf871b92eb456d2dd74d8/src/mono/mono/mini/mini-posix.c#L193-L210 only after attempting to walk native and managed stacks https://github.com/dotnet/runtime/blob/61d3943de41e948bb0ecf871b92eb456d2dd74d8/src/mono/mono/mini/mini-exceptions.c#L2992-L3012 ## Alternatives If there is any particular reason to preserve the order of sa_sigaction/sa_handler with respect to PROCNotifyProcessShutdown and PROCCreateCrashDumpIfEnabled for CoreCLR, a config knob can be added to allow Android CoreCLR to opt into the swapped ordering behavior. This may be in the form of config property key/values https://github.com/dotnet/runtime/blob/54ca569eb62800cdb725d776e3dd2e564028594d/src/coreclr/dlls/mscoree/exports.cpp#L237-L238 or `clrconfigvalues`. That way AndroidSDK/AndroidAppBuilder may opt-in at build-time. Given that the history of the ordering didn't reveal any problems with swapping the order, we can fallback to this behavior if the order swap causes problems down the line. The other way around is more restrictive. Should we first introduce all the overhead to enable an opt-in/opt-out config knob, and later discover that no platforms need to invoke their previous handlers before PROCNotifyProcessShutdown/PROCCreateCrashDumpIfEnabled, it seems harder to justify removing the knob.
This was referenced Feb 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Migrates XML documentation from dotnet-api-docs into
///comments and adds runnable code samples for 11 coreSystem.Collections.Generictypes (351 DocFX UIDs, 11 sample files, ~1,500 lines). This is a pilot for an LLM agent-driven approach to migrating and enriching API documentation at scale acrossdotnet/runtime.Approach: LLM agent fleet
The
slashCLI toolkit and its companion agent skill are purpose-built for LLM agent automation. The workflow is designed so that LLM agents do the work — auditing doc coverage, writing runnable code samples, registering them insamples.json, and running the tool to generate///comments. Each type is an independent work unit that an agent processes end-to-end with no human coordination required between agents.The tool is deterministic and repeatable:
///comments are entirely derived from inputs (dotnet-api-docsXML, sample files,samples.json), so it can be re-run any number of times without loss. Agents write the inputs; the tool writes the source. This separation means agents never hand-edit///comments — they produce samples and mappings, and the tool does the rest.Fleet estimate for dotnet/runtime
Excluding non-runtime frameworks (WinForms, WPF, WCF, ASP.NET WebForms, etc.),
dotnet-api-docscontains an estimated 8,000–10,000 runtime-relevant types.Sample prioritization — selecting which types get samples first based on usage data (page views, NuGet downloads, API telemetry) — is an open constraint that should be resolved before scaling beyond the pilot.
See SAMPLES-REPORT.md for full context — design goals, tradeoffs, the
#regiondivergence, duplication management, batching strategy, and CI integration path.Key files by type
All links point to the
dev/richlander/collections-xmldocsbranch.Samples infrastructure
Directory.Build.propsDirectory.Build.targetseng/run-samples.shSample files (runnable file-based apps with local functions as boundaries)
List.Examples.csDictionary.Examples.csStack.Examples.csLinkedList.Examples.csOrderedDictionary.Examples.cssamples.json (maps DocFX UIDs → sample methods; one per-type fragment, one merged per library)
samples.json(System.Collections)samples.json(CoreLib)LinkedList.samples.jsonStack.samples.jsonList.samples.json