Skip to content

Implement GetCommandLineArgs fallback on Unix - #131431

Open
am11 wants to merge 4 commits into
dotnet:mainfrom
am11:feature/GetCommandLineArgs-Unix
Open

am11 wants to merge 4 commits into
dotnet:mainfrom
am11:feature/GetCommandLineArgs-Unix

Conversation

@am11

@am11 am11 commented Jul 27, 2026 •

Copy link
Copy Markdown
Member

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-runtime
See info in area-owners.md if you want to be subscribed.

Comment thread src/native/libs/System.Native/pal_process.c Outdated
Comment thread src/native/minipal/getcmdline.h Outdated
Comment thread src/native/minipal/getcmdline.h Outdated
@am11
am11 force-pushed the feature/GetCommandLineArgs-Unix branch 3 times, most recently from fd686e7 to 675263d Compare July 28, 2026 16:33
Comment thread src/native/minipal/getcmdline.h Outdated
Comment thread src/native/minipal/getcmdline.h Outdated
@am11
am11 requested a review from agocke August 9, 2026 12:59
@jkotas
jkotas requested a lite review from Copilot August 13, 2026 00:42

Copilot AI 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.

Pull request overview

Implements a Unix/WASI/browser fallback path for Environment.GetCommandLineArgs() when Environment.s_commandLineArgs isn’t initialized (hosted-library scenario), by adding a System.Native entrypoint that retrieves argv via a new minipal_getcmdline helper and wiring it into CoreLib’s GetCommandLineArgsNative().

Changes:

  • Add minipal_getcmdline and expose it via SystemNative_GetCommandLine / SystemNative_FreeCommandLine.
  • Update CoreLib Unix/Browser implementation to call the new System.Native interop and remove the prior stubbed-out implementation.
  • Broaden the fallback test coverage beyond “Windows CoreCLR only” (still excluding Mono).

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/native/minipal/getcmdline.h New minipal helper that attempts to obtain argv across multiple Unix-like targets (plus WASI/browser).
src/native/libs/System.Native/pal_process.h Declares new SystemNative_GetCommandLine / SystemNative_FreeCommandLine exports.
src/native/libs/System.Native/pal_process.c Implements the new exports by delegating to minipal_getcmdline.
src/native/libs/System.Native/pal_process_wasi.c Implements the new exports for WASI builds.
src/native/libs/System.Native/entrypoints.c Registers the new exports for System.Native DllImport dispatch.
src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetCommandLine.cs Adds LibraryImport declarations for SystemNative_GetCommandLine / SystemNative_FreeCommandLine.
src/libraries/System.Private.CoreLib/src/System/Environment.UnixOrBrowser.cs Adds a Unix/Browser GetCommandLineArgsNative() implementation that calls the new interop.
src/libraries/System.Private.CoreLib/src/System/Environment.Unix.cs Removes the old stub GetCommandLineArgsNative() implementation.
src/libraries/System.Private.CoreLib/src/System/Environment.Browser.cs Removes the old Browser stub for GetCommandLineArgsNative().
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems Includes the new interop source file in CoreLib build items.
src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/Environment.GetCommandLineArgs.cs Updates conditions so fallback tests run on non-Mono (and parser tests run on Windows non-Mono).
Suppressed comments (1)

src/native/minipal/getcmdline.h:83

  • The /proc/self/cmdline reader doesn't check whether the initial malloc succeeded, and it doesn't handle read() returning -1 (including EINTR). As written, a read error after partial data can silently return a truncated/invalid argv buffer, and a NULL buf would be dereferenced.
    size_t bufSize = 1024;
    char* buf = (char*)malloc(bufSize);
    size_t totalBytes = 0;
    ssize_t bytesRead;

Comment thread src/native/minipal/getcmdline.h Outdated
@am11
am11 force-pushed the feature/GetCommandLineArgs-Unix branch from 9edbb0c to a95fc33 Compare October 22, 2026 17:41
@am11
am11 requested a review from jkotas October 22, 2026 17:42
Comment thread src/native/libs/System.Native/pal_process.c
@jkotas

jkotas commented Oct 23, 2026

Copy link
Copy Markdown
Member

I am not sure about this feature. It is a lot of OS-specific code that tends to be difficult to port, and the benefit of feature is debatable - code outside the main executable has no business reverse engineering the app command line.

@elinor-fung @dotnet/appmodel Thoughts?

@am11

am11 commented Oct 23, 2026

Copy link
Copy Markdown
Member Author

code outside the main executable has no business reverse engineering the app command line

Only the calling assembly is outside the executing assembly; from the OS viewpoint, it is still the same executing .NET app. The only true "outside code" scenario would be #21941, which does raise valid security concerns. Even so, it falls under the "when you need it, you need it" rule (dotnet/msbuild#15374), especially since desktop operating systems explicitly allow it.

@jkotas

jkotas commented Oct 23, 2026

Copy link
Copy Markdown
Member

Only the calling assembly is outside the executing assembly; from the OS viewpoint, it is still the same executing .NET app

My comment was about code hygiene. I do not think it is a good practice for libraries to fish for command line arguments of the main program.

Apparently, Rust made equivalent of this API work in dynamic libraries. They use a creative solution that works for glibc (but it won't work for musl)
https://github.com/rust-lang/rust/blob/fe2b43dd212769ef40ae2e32e5c5f5364642b82b/library/std/src/sys/args/unix.rs#L153

return PackCommandLine(1, browserArgs, argc);
#elif defined(__linux__) || defined(__sun)
int fd;
while ((fd = open("/proc/self/cmdline", O_RDONLY | O_CLOEXEC)) < 0 && errno == EINTR);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm pretty skeptical that we should return different behavior for this API depending on whether the user registered the /proc file system.

@am11 am11 Oct 24, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Does .NET officially support a system without /proc? Do we have the CI coverage? I have done ad-hoc testing and fixes in the past #62513, so I know how that testing looks like in practice; system without procfs also means system without ptrace, which PAL depends on and all those else branches are never holistically tested, and just like qemu it's "if it works, it works; use at your own risk" plan.

}
#endif

#if !defined(TARGET_BROWSER) && (defined(__linux__) || defined(__sun) || defined(__FreeBSD__) || defined(__APPLE__))

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.

Suggested change
#if !defined(TARGET_BROWSER) && (defined(__linux__) || defined(__sun) || defined(__FreeBSD__) || defined(__APPLE__))
#if defined(__linux__) || defined(__sun) || defined(__FreeBSD__) || defined(__APPLE__)

Comment thread src/native/libs/System.Native/pal_process.c

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants