dotnet / dotnet/runtime

GetCommandLineArgsNative fallback used for hosted libraries is not implemented on non-Windows

Open
#128,545 5 comments 2 reactions 0 assignees View on GitHub
area-System.Runtime
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

### Description

Under NativeAOT, it is possible create a native library which can be consumed by a native executable (e.g. a .so shared library on Linux). On such a setup, `Environment.GetCommandLineArgs()` returns an empty array on Linux. It does not do this under Windows (instead functioning completely as "expected"). This means Environment.GetCommandLineArgs()[0] will throw under Linux in this type of setup.

### Reproduction Steps

```cs
using System;
using System.Runtime.InteropServices;

namespace Program;

internal static class Program
{
[UnmanagedCallersOnly(EntryPoint = "Test")]
public static void Test()
{
try
{
Console.WriteLine($"Environment.GetCommandLineArgs()[0]: {Environment.GetCommandLineArgs()[0]}");
}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex}");
}
}
}
```
```xml


net10.0
Library
Shared
true
libProgram

```
`dotnet publish -r linux-x64`
```c
#include
#include

typedef void (*TestFunc)(void);

int main(void)
{
void* handle = dlopen("./libProgram.so", RTLD_NOW | RTLD_LOCAL);
TestFunc testFunc = (TestFunc)dlsym(handle, "Test");
testFunc();
}
```

### Expected behavior

[Environment.GetCommandLineArgs docs](https://learn.microsoft.com/en-us/dotnet/api/system.environment.getcommandlineargs) states:
> The first element in the array contains the file name of the executing program. If the file name is not available, the first element is equal to [String.Empty](https://learn.microsoft.com/en-us/dotnet/api/system.string.empty?view=netframework-4.8.1#system-string-empty).

This implies that the array returned should have at least 1 element. As such, an empty array should not be returned (at the best least it should have 1 element with an empty string, so Environment.GetCommandLineArgs()[0] will not throw).

### Actual behavior

Environment.GetCommandLineArgs()[0] throws.

### Regression?

_No response_

### Known Workarounds

Do not assume Environment.GetCommandLineArgs() has at least 1 element. try/catch for third party code that makes such assumptions.

### Configuration

This was originally encountered on Android with linux-bionic (as such under NativeAOT practically means you would be making a shared library anyways). On standard Linux (Ubuntu), this issue also occurs. On Windows, this issue does not occur (it's even able to provide command line args for the host exe just fine).

### Other information

This was [originally encountered with System.CommandLine](https://github.com/dotnet/command-line-api/issues/2812) as the RootCommand ctor triggers this exception.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.