summaryrefslogtreecommitdiff
path: root/src/pal/tests
diff options
context:
space:
mode:
authorKoundinya Veluri <kouvel@users.noreply.github.com>2018-12-18 14:32:38 -0800
committerGitHub <noreply@github.com>2018-12-18 14:32:38 -0800
commitd67f84b05e02988276eb140194d914185e9c2ca3 (patch)
tree9d47a560f82f57ac75b0a754ac81a802e766b5e0 /src/pal/tests
parentb7b1aa016ac4eb13a54e49c1f9e137b9dab01a66 (diff)
downloadcoreclr-d67f84b05e02988276eb140194d914185e9c2ca3.tar.gz
coreclr-d67f84b05e02988276eb140194d914185e9c2ca3.tar.bz2
coreclr-d67f84b05e02988276eb140194d914185e9c2ca3.zip
Update named mutex PAL tests to include case of file locks being inherited by child process (#21496)
Included case fixed by https://github.com/dotnet/coreclr/pull/21458. Fixes https://github.com/dotnet/coreclr/issues/21494.
Diffstat (limited to 'src/pal/tests')
-rw-r--r--src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp72
1 files changed, 72 insertions, 0 deletions
diff --git a/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp b/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp
index a9d46b3d73..6635d76a80 100644
--- a/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp
+++ b/src/pal/tests/palsuite/threading/NamedMutex/test1/namedmutex.cpp
@@ -837,6 +837,67 @@ DWORD AbandonTests_Child_AbruptExit(void *arg = nullptr)
return 0;
}
+// This child process acquires the mutex lock, creates another child process (to ensure that file locks are not inherited), and
+// abandons the mutex abruptly. The second child process detects the abandonment and abandons the mutex again for the parent to
+// detect. Issue: https://github.com/dotnet/coreclr/issues/21455
+DWORD AbandonTests_Child_FileLocksNotInherited_Parent_AbruptExit(void *arg = nullptr)
+{
+ const char *testName = "AbandonTests";
+
+ DWORD currentPid = test_getpid();
+ TestAssert(currentPid != g_parentPid); // this test needs to run in a separate process
+
+ {
+ char name[MaxPathSize];
+ AutoCloseMutexHandle m;
+
+ // ... root parent waits for child to lock mutex
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix));
+ TestAssert(m != nullptr);
+ TestAssert(WaitForSingleObject(m, 0) == WAIT_OBJECT_0);
+
+ // Start a child process while holding the lock on the mutex, to ensure that file locks are not inherited by the
+ // immediate child, such that the immediate child would be able to detect the mutex being abandoned below. This process
+ // does not communicate with the root parent, it only communicates to the immediate child by abandoning the mutex. The
+ // immediate child communicates with the root parent to complete the test.
+ TestAssert(StartProcess("AbandonTests_Child_FileLocksNotInherited_Child_AbruptExit")); // immediate child waits on mutex
+
+ Sleep(g_expectedTimeoutMilliseconds); // wait for immediate child to wait on mutex
+ m.Abandon(); // don't close the mutex
+ }
+
+ TestAssert(test_kill(currentPid) == 0); // abandon the mutex abruptly
+ return 0;
+}
+
+DWORD AbandonTests_Child_FileLocksNotInherited_Child_AbruptExit(void *arg = nullptr)
+{
+ const char *testName = "AbandonTests";
+
+ DWORD currentPid = test_getpid();
+ TestAssert(currentPid != g_parentPid); // this test needs to run in a separate process
+
+ AutoCloseMutexHandle childRunningEvent, parentEvents[2], childEvents[2];
+ TestAssert(InitializeChild(testName, childRunningEvent, parentEvents, childEvents));
+ int ei = 0;
+
+ {
+ char name[MaxPathSize];
+ AutoCloseMutexHandle m;
+
+ // ... immediate parent expects child to wait on mutex
+ TestCreateMutex(m, BuildName(testName, name, GlobalPrefix, NamePrefix));
+ TestAssert(m != nullptr);
+ TestAssert(WaitForSingleObject(m, FailTimeoutMilliseconds) == WAIT_ABANDONED_0); // attempt to lock and see abandoned mutex
+ TestAssert(YieldToParent(parentEvents, childEvents, ei)); // root parent waits on mutex
+ Sleep(g_expectedTimeoutMilliseconds); // wait for root parent to wait on mutex
+ m.Close(); // close mutex without releasing lock (root parent expects the mutex to be abandoned)
+ }
+
+ UninitializeChild(childRunningEvent, parentEvents, childEvents);
+ return 0;
+}
+
DWORD PALAPI AbandonTests_Child_TryLock(void *arg)
{
const char *testName = "AbandonTests";
@@ -878,6 +939,9 @@ bool AbandonTests()
TestAssert(StartProcess("AbandonTests_Child_AbruptExit"));
TestAssert(AbandonTests_Parent());
+ TestAssert(StartProcess("AbandonTests_Child_FileLocksNotInherited_Parent_AbruptExit"));
+ TestAssert(AbandonTests_Parent());
+
return true;
}
@@ -1049,6 +1113,14 @@ int __cdecl main(int argc, char **argv)
{
AbandonTests_Child_AbruptExit();
}
+ else if (test_strcmp(argv[2], "AbandonTests_Child_FileLocksNotInherited_Parent_AbruptExit") == 0)
+ {
+ AbandonTests_Child_FileLocksNotInherited_Parent_AbruptExit();
+ }
+ else if (test_strcmp(argv[2], "AbandonTests_Child_FileLocksNotInherited_Child_AbruptExit") == 0)
+ {
+ AbandonTests_Child_FileLocksNotInherited_Child_AbruptExit();
+ }
else if (test_strcmp(argv[2], "AbandonTests_Child_TryLock") == 0)
{
AbandonTests_Child_TryLock();