Skip to content

Commit 6ee57c0

Browse files
authored
De-duplicate Unix Environment variables between Mono and native AOT (dotnet#76853)
* De-duplicate Unix Environment variables between Mono and native AOT CoreCLR left on Win32 PAL * Delete unused file
1 parent f2de14d commit 6ee57c0

File tree

8 files changed

+12
-196
lines changed

8 files changed

+12
-196
lines changed

src/coreclr/nativeaot/System.Private.CoreLib/src/Interop/Windows/Interop.Libraries.cs

-11
This file was deleted.

src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj

-7
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,6 @@
282282
<Link>Interop\Windows\OleAut32\Interop.VariantClear.cs</Link>
283283
</Compile>
284284
<Compile Include="System\Environment.NativeAot.Windows.cs" />
285-
<Compile Include="System\Environment.NativeAot.Win32.cs" />
286285
<Compile Include="$(CommonPath)\Interop\Windows\Kernel32\Interop.GetTickCount64.cs">
287286
<Link>Interop\Windows\Kernel32\Interop.GetTickCount64.cs</Link>
288287
</Compile>
@@ -325,18 +324,12 @@
325324
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Exit.cs">
326325
<Link>Interop\Unix\System.Native\Interop.Exit.cs</Link>
327326
</Compile>
328-
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.GetEnv.cs">
329-
<Link>Interop\Unix\System.Native\Interop.GetEnv.cs</Link>
330-
</Compile>
331327
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.SchedGetCpu.cs">
332328
<Link>Interop\Unix\System.Native\Interop.SchedGetCpu.cs</Link>
333329
</Compile>
334330
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Threading.cs">
335331
<Link>Interop\Unix\System.Native\Interop.Threading.cs</Link>
336332
</Compile>
337-
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.GetEnviron.cs">
338-
<Link>Interop\Unix\System.Native\Interop.GetEnviron.cs</Link>
339-
</Compile>
340333
</ItemGroup>
341334
<ItemGroup>
342335
<Compile Include="$(CompilerCommonPath)\System\Collections\Generic\ArrayBuilder.cs">
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.Collections;
5-
using System.Collections.Generic;
6-
using System.Diagnostics;
74
using System.Diagnostics.CodeAnalysis;
8-
using System.Runtime.InteropServices;
95
using System.Runtime;
10-
using System.Text;
116
using System.Threading;
127

138
namespace System
@@ -16,157 +11,9 @@ public static partial class Environment
1611
{
1712
internal static int CurrentNativeThreadId => ManagedThreadId.Current;
1813

19-
private static Dictionary<string, string> s_environment;
20-
21-
private static string? GetEnvironmentVariableCore(string variable)
22-
{
23-
Debug.Assert(variable != null);
24-
25-
if (s_environment == null)
26-
{
27-
return Marshal.PtrToStringUTF8(Interop.Sys.GetEnv(variable));
28-
}
29-
30-
lock (s_environment)
31-
{
32-
variable = TrimStringOnFirstZero(variable);
33-
s_environment.TryGetValue(variable, out string? value);
34-
return value;
35-
}
36-
}
37-
38-
private static void SetEnvironmentVariableCore(string variable, string? value)
39-
{
40-
Debug.Assert(variable != null);
41-
42-
EnsureEnvironmentCached();
43-
lock (s_environment)
44-
{
45-
variable = TrimStringOnFirstZero(variable);
46-
value = value == null ? null : TrimStringOnFirstZero(value);
47-
if (string.IsNullOrEmpty(value))
48-
{
49-
s_environment.Remove(variable);
50-
}
51-
else
52-
{
53-
s_environment[variable] = value;
54-
}
55-
}
56-
}
57-
58-
public static IDictionary GetEnvironmentVariables()
59-
{
60-
var results = new Hashtable();
61-
62-
EnsureEnvironmentCached();
63-
lock (s_environment)
64-
{
65-
foreach (var keyValuePair in s_environment)
66-
{
67-
results.Add(keyValuePair.Key, keyValuePair.Value);
68-
}
69-
}
70-
71-
return results;
72-
}
73-
74-
private static string TrimStringOnFirstZero(string value)
75-
{
76-
int index = value.IndexOf('\0');
77-
if (index >= 0)
78-
{
79-
return value.Substring(0, index);
80-
}
81-
return value;
82-
}
83-
84-
private static void EnsureEnvironmentCached()
85-
{
86-
if (s_environment == null)
87-
{
88-
Interlocked.CompareExchange(ref s_environment, GetSystemEnvironmentVariables(), null);
89-
}
90-
}
91-
92-
private static Dictionary<string, string> GetSystemEnvironmentVariables()
93-
{
94-
var results = new Dictionary<string, string>();
95-
96-
IntPtr block = Interop.Sys.GetEnviron();
97-
if (block != IntPtr.Zero)
98-
{
99-
try
100-
{
101-
IntPtr blockIterator = block;
102-
103-
// Per man page, environment variables come back as an array of pointers to strings
104-
// Parse each pointer of strings individually
105-
while (ParseEntry(blockIterator, out string? key, out string? value))
106-
{
107-
if (key != null && value != null)
108-
{
109-
try
110-
{
111-
// Add may throw if the environment block was corrupted leading to duplicate entries.
112-
// We allow such throws and eat them (rather than proactively checking for duplication)
113-
// to provide a non-fatal notification about the corruption.
114-
results.Add(key, value);
115-
}
116-
catch (ArgumentException) { }
117-
}
118-
119-
// Increment to next environment variable entry
120-
blockIterator += IntPtr.Size;
121-
}
122-
}
123-
finally
124-
{
125-
Interop.Sys.FreeEnviron(block);
126-
}
127-
}
128-
129-
return results;
130-
131-
// Use a local, unsafe function since we cannot use `yield return` inside of an `unsafe` block
132-
static unsafe bool ParseEntry(IntPtr current, out string? key, out string? value)
133-
{
134-
// Setup
135-
key = null;
136-
value = null;
137-
138-
// Point to current entry
139-
byte* entry = *(byte**)current;
140-
141-
// Per man page, "The last pointer in this array has the value NULL"
142-
// Therefore, if entry is null then we're at the end and can bail
143-
if (entry == null)
144-
return false;
145-
146-
// Parse each byte of the entry until we hit either the separator '=' or '\0'.
147-
// This finds the split point for creating key/value strings below.
148-
// On some old OS, the environment block can be corrupted.
149-
// Some will not have '=', so we need to check for '\0'.
150-
byte* splitpoint = entry;
151-
while (*splitpoint != '=' && *splitpoint != '\0')
152-
splitpoint++;
153-
154-
// Skip over entries starting with '=' and entries with no value (just a null-terminating char '\0')
155-
if (splitpoint == entry || *splitpoint == '\0')
156-
return true;
157-
158-
// The key is the bytes from start (0) until our splitpoint
159-
key = new string((sbyte*)entry, 0, checked((int)(splitpoint - entry)));
160-
// The value is the rest of the bytes starting after the splitpoint
161-
value = new string((sbyte*)(splitpoint + 1));
162-
163-
return true;
164-
}
165-
}
14+
public static long TickCount64 => (long)RuntimeImports.RhpGetTickCount64();
16615

16716
[DoesNotReturn]
16817
private static void ExitRaw() => Interop.Sys.Exit(s_latchedExitCode);
169-
170-
public static long TickCount64 => (long)RuntimeImports.RhpGetTickCount64();
17118
}
17219
}

src/coreclr/nativeaot/System.Private.CoreLib/src/System/Environment.NativeAot.Win32.cs

-14
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.Buffers;
5-
using System.Diagnostics;
6-
using System.Runtime.InteropServices;
4+
using System.Diagnostics.CodeAnalysis;
75

86
namespace System
97
{
@@ -12,5 +10,8 @@ public static partial class Environment
1210
internal static int CurrentNativeThreadId => unchecked((int)Interop.Kernel32.GetCurrentThreadId());
1311

1412
public static long TickCount64 => (long)Interop.Kernel32.GetTickCount64();
13+
14+
[DoesNotReturn]
15+
private static void ExitRaw() => Interop.Kernel32.ExitProcess(s_latchedExitCode);
1516
}
1617
}

src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems

+7
Original file line numberDiff line numberDiff line change
@@ -2049,6 +2049,12 @@
20492049
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.GetDefaultTimeZone.AnyMobile.cs" Condition="'$(TargetsAndroid)' == 'true' or '$(TargetsLinuxBionic)' == 'true' or '$(IsiOSLike)' == 'true'">
20502050
<Link>Common\Interop\Unix\System.Native\Interop.GetDefaultTimeZone.AnyMobile.cs</Link>
20512051
</Compile>
2052+
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.GetEnv.cs">
2053+
<Link>Common\Interop\Unix\System.Native\Interop.GetEnv.cs</Link>
2054+
</Compile>
2055+
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.GetEnviron.cs">
2056+
<Link>Common\Interop\Unix\System.Native\Interop.GetEnviron.cs</Link>
2057+
</Compile>
20522058
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.GetHostName.cs">
20532059
<Link>Common\Interop\Unix\System.Native\Interop.GetHostName.cs</Link>
20542060
</Compile>
@@ -2205,6 +2211,7 @@
22052211
<Compile Include="$(MSBuildThisFileDirectory)System\Environment.OSVersion.OSX.cs" Condition="'$(IsOSXLike)' == 'true' AND '$(TargetsMacCatalyst)' != 'true'" />
22062212
<Compile Include="$(MSBuildThisFileDirectory)System\Environment.OSVersion.MacCatalyst.cs" Condition="'$(TargetsMacCatalyst)' == 'true'" />
22072213
<Compile Include="$(MSBuildThisFileDirectory)System\Environment.GetFolderPathCore.Unix.cs" Condition="'$(IsiOSLike)' != 'true' and '$(TargetsAndroid)' != 'true' and '$(TargetsLinuxBionic)' != 'true'" />
2214+
<Compile Include="$(MSBuildThisFileDirectory)System\Environment.Variables.Unix.cs" Condition="'$(FeatureCoreCLR)' != 'true'" />
22082215
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CalendarData.Unix.cs" />
22092216
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CultureData.Unix.cs" />
22102217
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CultureInfo.Unix.cs" />

src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj

-7
Original file line numberDiff line numberDiff line change
@@ -279,14 +279,7 @@
279279
<Compile Include="$(BclSourcesRoot)\System\Threading\ThreadPool.Mono.cs" />
280280
</ItemGroup>
281281
<ItemGroup Condition="'$(TargetsUnix)' == 'true' or '$(TargetsBrowser)' == 'true'">
282-
<Compile Include="$(BclSourcesRoot)\System\Environment.Unix.Mono.cs" />
283282
<Compile Include="$(BclSourcesRoot)\System\Threading\LowLevelLifoSemaphore.Unix.Mono.cs" />
284-
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.GetEnv.cs">
285-
<Link>Common\Interop\Unix\System.Native\Interop.GetEnv.cs</Link>
286-
</Compile>
287-
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.GetEnviron.cs">
288-
<Link>Common\Interop\Unix\System.Native\Interop.GetEnviron.cs</Link>
289-
</Compile>
290283
</ItemGroup>
291284
<ItemGroup Condition="'$(TargetsBrowser)' == 'true'">
292285
<Compile Include="$(BclSourcesRoot)\System\Threading\TimerQueue.Browser.Mono.cs" />

0 commit comments

Comments
 (0)