Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.InteropServices;
using System.Threading;

internal static partial class Interop
{
internal static partial class Sys
{
private static volatile int s_pageSize;

internal static int PageSize
{
get
{
int size = s_pageSize;
if (size == 0)
{
Interlocked.CompareExchange(ref s_pageSize, GetPageSize(), 0);
size = s_pageSize;
}

return size;
}
}

[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetPageSize")]

Check failure on line 28 in src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs

View check run for this annotation

Azure Pipelines / runtime (Build linux-x64 Debug Mono_Interpreter_LibrariesTests)

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs#L28

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs(28,24): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'Libraries' does not exist in the current context

Check failure on line 28 in src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs

View check run for this annotation

Azure Pipelines / runtime (Build linux-arm64 Release NativeAOT_Libraries)

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs#L28

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs(28,24): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'Libraries' does not exist in the current context

Check failure on line 28 in src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs

View check run for this annotation

Azure Pipelines / runtime (Build linux-x64 Debug Mono_MiniJIT_LibrariesTests)

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs#L28

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs(28,24): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'Libraries' does not exist in the current context

Check failure on line 28 in src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs

View check run for this annotation

Azure Pipelines / runtime (Build linux-arm64 Debug Mono_MiniJIT_LibrariesTests)

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs#L28

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs(28,24): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'Libraries' does not exist in the current context

Check failure on line 28 in src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs

View check run for this annotation

Azure Pipelines / runtime (Build osx-x64 Debug Mono_MiniJIT_LibrariesTests)

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs#L28

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs(28,24): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'Libraries' does not exist in the current context

Check failure on line 28 in src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs

View check run for this annotation

Azure Pipelines / runtime (Build linux_musl-x64 Debug CoreCLR_Libraries)

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs#L28

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs(28,24): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'Libraries' does not exist in the current context

Check failure on line 28 in src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs

View check run for this annotation

Azure Pipelines / runtime (Build linux-x64 Debug CoreCLR_Libraries)

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs#L28

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs(28,24): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'Libraries' does not exist in the current context

Check failure on line 28 in src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs

View check run for this annotation

Azure Pipelines / runtime (Build linux-arm64 Debug Libraries_CheckedCoreCLR)

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs#L28

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs(28,24): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'Libraries' does not exist in the current context

Check failure on line 28 in src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs

View check run for this annotation

Azure Pipelines / runtime (Build osx-arm64 Release NativeAOT_Libraries)

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs#L28

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs(28,24): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'Libraries' does not exist in the current context

Check failure on line 28 in src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs

View check run for this annotation

Azure Pipelines / runtime (Build osx-x64 Debug Libraries_CheckedCoreCLR)

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs#L28

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs(28,24): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'Libraries' does not exist in the current context

Check failure on line 28 in src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs

View check run for this annotation

Azure Pipelines / runtime (Build osx-x64 Debug CoreCLR_Libraries)

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs#L28

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs(28,24): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'Libraries' does not exist in the current context

Check failure on line 28 in src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs

View check run for this annotation

Azure Pipelines / runtime (Build browser-wasm linux Release LibraryTests_EAT)

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs#L28

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs(28,24): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'Libraries' does not exist in the current context

Check failure on line 28 in src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs

View check run for this annotation

Azure Pipelines / runtime (Build browser-wasm linux Release LibraryTests)

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs#L28

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs(28,24): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'Libraries' does not exist in the current context

Check failure on line 28 in src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs

View check run for this annotation

Azure Pipelines / runtime

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs#L28

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs(28,24): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'Libraries' does not exist in the current context

Check failure on line 28 in src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs

View check run for this annotation

Azure Pipelines / runtime

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs#L28

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs(28,24): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'Libraries' does not exist in the current context

Check failure on line 28 in src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs

View check run for this annotation

Azure Pipelines / runtime

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs#L28

src/libraries/Common/src/Interop/Unix/Interop.GetPageSize.cs(28,24): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'Libraries' does not exist in the current context
private static partial int GetPageSize();
}
}
72 changes: 71 additions & 1 deletion src/libraries/System.Threading/tests/MutexTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,10 @@ public void MutualExclusionTest()
public void Ctor_InvalidNames_Unix()
{
AssertExtensions.Throws<ArgumentException>("name", null, () => new Mutex(new string('a', 1000), options: default));
AssertExtensions.Throws<IOException>("name", null, () => new Mutex("Foo/Bar", options: default));
AssertExtensions.Throws<IOException>("name", null, () => new Mutex("Foo\\Bar", options: default));
AssertExtensions.Throws<IOException>("name", null, () => new Mutex("Global\\Foo/Bar", options: default));
AssertExtensions.Throws<IOException>("name", null, () => new Mutex("Global\\Foo\\Bar", options: default));
}

[Theory]
Expand Down Expand Up @@ -971,9 +975,75 @@ public void NamedMutex_DisposeWhenLockedRaceTest()
}
}

[ConditionalFact(nameof(IsCrossProcessNamedMutexSupported))]
[PlatformSpecific(TestPlatforms.AnyUnix)]
public void NamedMutex_OtherEvent_NotCompatible()
{
using Mutex m = new Mutex(Guid.NewGuid().ToString("N"), options: default);
using ManualResetEvent mre = new(false);

Assert.Throws<PlatformNotSupportedException>(() => WaitHandle.WaitAny(new WaitHandle[] { m, mre }, 0));
}

[ConditionalFact(nameof(IsCrossProcessNamedMutexSupported))]
[PlatformSpecific(TestPlatforms.AnyUnix)]
public void NamedMutex_InvalidSharedMemoryHeaderVersion()
{
string name = Guid.NewGuid().ToString("N");
string path = $"/tmp/.dotnet/shm/global/{name}";
using (FileStream fs = File.Create(path))
using (BinaryWriter bw = new(fs))
{
bw.Write((byte)1); // Write the shared memory type (mutex)
bw.Write((byte)2); // Write an invalid version number
// Make the file large enough for a valid named mutex file and divisible by page size (it should always be under one page).
fs.SetLength(Interop.Sys.GetPageSize());
}

Assert.Throws<WaitHandleCannotBeOpenedException>(() => new Mutex($"Global\\{name}"));
}

[ConditionalFact(nameof(IsCrossProcessNamedMutexSupported))]
[PlatformSpecific(TestPlatforms.AnyUnix)]
public void NamedMutex_InvalidSharedMemoryHeaderKind()
{
string name = Guid.NewGuid().ToString("N");
string path = $"/tmp/.dotnet/shm/global/{name}";
using (FileStream fs = File.Create(path))
using (BinaryWriter bw = new(fs))
{
fs.SetLength(Interop.Sys.GetPageSize());
fs.Position = 0;
bw.Write((byte)2); // Write the shared memory type (invalid)
bw.Write((byte)1); // Write a version number
// Make the file large enough for a valid named mutex file and divisible by page size (it should always be under one page).
fs.SetLength(Interop.Sys.GetPageSize());
}

Assert.Throws<WaitHandleCannotBeOpenedException>(() => new Mutex($"Global\\{name}"));
}

[ConditionalFact(nameof(IsCrossProcessNamedMutexSupported))]
[PlatformSpecific(TestPlatforms.AnyUnix)]
public void NamedMutex_TooSmallSharedMemoryFile()
{
string name = Guid.NewGuid().ToString("N");
string path = $"/tmp/.dotnet/shm/global/{name}";
using (FileStream fs = File.Create(path))
using (BinaryWriter bw = new(fs))
{
bw.Write((byte)1); // Write the shared memory type (mutex)
bw.Write((byte)1); // Write an valid version number
// Make the file large enough for a valid named mutex file but not divisible by page size.
fs.SetLength(Interop.Sys.GetPageSize() - 1);
}

Assert.Throws<WaitHandleCannotBeOpenedException>(() => new Mutex($"Global\\{name}"));
}

public static TheoryData<string> GetValidNames()
{
var names = new TheoryData<string>() { Guid.NewGuid().ToString("N") };
var names = new TheoryData<string>() { Guid.NewGuid().ToString("N") };

// Windows native named mutexes and in-proc named mutexes support very long (1000+ char) names.
// Non-Windows cross-process named mutexes are emulated using file system. It imposes limit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,7 @@
Link="CommonTest\System\Diagnostics\Tracing\TestEventListener.cs" />
<Compile Include="$(CommonTestPath)System\Threading\ThreadTestHelpers.cs"
Link="CommonTest\System\Threading\ThreadTestHelpers.cs" />
<Compile Include="$(CommonPath)Interop\Unix\Interop.GetPageSize.cs"
Link="Common\Interop\Unix\Interop.GetPageSize.cs" />
</ItemGroup>
</Project>
1 change: 1 addition & 0 deletions src/native/libs/System.Native/entrypoints.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ static const Entry s_sysNative[] =
DllImportEntry(SystemNative_SchedSetAffinity)
DllImportEntry(SystemNative_SchedGetAffinity)
DllImportEntry(SystemNative_GetProcessPath)
DllImportEntry(SystemNative_GetPageSize)
DllImportEntry(SystemNative_GetNonCryptographicallySecureRandomBytes)
DllImportEntry(SystemNative_GetCryptographicallySecureRandomBytes)
DllImportEntry(SystemNative_GetUnixRelease)
Expand Down
7 changes: 7 additions & 0 deletions src/native/libs/System.Native/pal_process.c
Original file line number Diff line number Diff line change
Expand Up @@ -899,3 +899,10 @@ char* SystemNative_GetProcessPath(void)
{
return minipal_getexepath();
}

int32_t SystemNative_GetPageSize(void)
{
// The page size is the size of a memory page, which is the smallest unit of memory that can be
// allocated or deallocated. It is typically 4096 bytes on most systems.
return getpagesize();
}
2 changes: 2 additions & 0 deletions src/native/libs/System.Native/pal_process.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,5 @@ PALEXPORT int32_t SystemNative_SchedGetAffinity(int32_t pid, intptr_t* mask);
* resolving symbolic links. The caller is responsible for releasing the buffer.
*/
PALEXPORT char* SystemNative_GetProcessPath(void);

PALEXPORT int32_t SystemNative_GetPageSize(void);
Loading