Alt: Fall back to unfiltered enumeration on STATUS_OBJECT_NAME_NOT_FOUND (#130134)#10
Conversation
…Windows) In FileSystemEnumerator<T>.GetData() on Windows, when the first filtered NtQueryDirectoryFile call returns STATUS_OBJECT_NAME_NOT_FOUND, re-issue the query with no FileName filter and RestartScan, reverting to enumerate-all-then-filter for that directory. Some file system drivers (notably the Azure App Service run-from-package zip mount) report a zero-match filtered query with this status; the unfiltered retry lets the managed matching produce the empty result instead of throwing FileNotFoundException. Alternative approach for dotnet#130134. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Closing in favor of #8 (handle Does the package-backed share do the filtering?Yes. Two independent lines of evidence: Logical (from the issue's two probes): the behavior is asymmetric -- a matching pattern ( Empirical (harness, shipped .NET 10.0.9): I simulated both driver models at the
Only the filter-honoring model reproduces the reported exception. Since the real run-from-package mount does throw, it must be honoring the filter. Why that rules out this approachBecause the driver already evaluates the filter and reports "no matches," dotnet#127974's optimization is genuinely working on this share. This approach would discard that result and re-query with no filter, forcing the driver to return every entry to managed code to be filtered there -- exactly the O(all-entries) scan dotnet#127974 set out to eliminate, and precisely in the failing scenario (a selective pattern that matches nothing in a large directory, e.g. #8 instead returns empty immediately on Note This comment was generated by GitHub Copilot. |
Summary
Alternative approach for
dotnet/runtime#130134(zero-matchDirectory.GetFilesthrowsFileNotFoundExceptionon the Azure App Service run-from-package zip mount; regression fromdotnet/runtime#127974).See the primary/recommended approach in the peer PR from
jeffhandley/directory-getfiles-status-object.Root cause
dotnet/runtime#127974passes the search pattern toNtQueryDirectoryFileas an OS-level filter. A filtered query that matches zero entries returnsSTATUS_NO_SUCH_FILE(0xC000000F) on NTFS butSTATUS_OBJECT_NAME_NOT_FOUND(0xC0000034) on the zip mount; only the former is handled, so the latter throws.Change (this branch)
In
FileSystemEnumerator<T>.GetData()(Windows), when the first filteredNtQueryDirectoryFilecall returnsSTATUS_OBJECT_NAME_NOT_FOUND, re-issue the query with noFileNamefilter andRestartScan, reverting to the pre-#127974behavior for that directory (enumerate everything, then filter in managed code — which always runs anyway). The empty result is then produced without throwing.Trade-off vs. the recommended approach: behavior-preserving and also guards drivers that reject otherwise-valid filters, but adds an extra syscall on the affected path and is more code.
Validation
Validated with the same faithful
NtQueryDirectoryFilerepro harness: on the .NET 11 branch, the zero-match probe returns empty withcount = 0(was throwing) while a matching pattern still returnscount = 1.Note
This pull request (including its description) was created by GitHub Copilot.