summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/pal/inc/pal.h7
-rw-r--r--src/pal/src/include/pal/palinternal.h19
-rw-r--r--src/pal/src/include/pal/process.h8
-rw-r--r--src/pal/src/include/pal/sharedmemory.h57
-rw-r--r--src/pal/src/include/pal/sharedmemory.inl41
-rw-r--r--src/pal/src/include/pal/stackstring.hpp58
-rw-r--r--src/pal/src/init/pal.cpp52
-rw-r--r--src/pal/src/sharedmemory/sharedmemory.cpp148
-rw-r--r--src/pal/src/synchobj/mutex.cpp59
-rw-r--r--src/pal/src/thread/process.cpp31
10 files changed, 337 insertions, 143 deletions
diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h
index a7f0ff5d74..2a51d584ad 100644
--- a/src/pal/inc/pal.h
+++ b/src/pal/inc/pal.h
@@ -442,6 +442,13 @@ BOOL
PALAPI
PAL_NotifyRuntimeStarted(VOID);
+#ifdef __APPLE__
+PALIMPORT
+LPCSTR
+PALAPI
+PAL_GetApplicationGroupId();
+#endif // __APPLE__
+
static const int MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH = MAX_PATH;
PALIMPORT
diff --git a/src/pal/src/include/pal/palinternal.h b/src/pal/src/include/pal/palinternal.h
index 0e37ba84c0..a66ef7e18e 100644
--- a/src/pal/src/include/pal/palinternal.h
+++ b/src/pal/src/include/pal/palinternal.h
@@ -622,6 +622,8 @@ function_name() to call the system's implementation
we'll catch any definition conflicts */
#include <sys/socket.h>
+#include <pal/stackstring.hpp>
+
#if !HAVE_INFTIM
#define INFTIM -1
#endif // !HAVE_INFTIM
@@ -631,6 +633,8 @@ function_name() to call the system's implementation
#undef assert
#define assert (Use__ASSERTE_instead_of_assert) assert
+#define string_countof(a) (sizeof(a) / sizeof(a[0]) - 1)
+
#ifndef __ANDROID__
#define TEMP_DIRECTORY_PATH "/tmp/"
#else
@@ -641,6 +645,16 @@ function_name() to call the system's implementation
#define PROCESS_PIPE_NAME_PREFIX ".dotnet-pal-processpipe"
+#ifdef __APPLE__
+#define APPLICATION_CONTAINER_BASE_PATH_SUFFIX "/Library/Group Containers/"
+
+// Not much to go with, but Max semaphore length on Mac is 31 characters. In a sandbox, the semaphore name
+// must be prefixed with an application group ID. This will be 10 characters for developer ID and extra 2
+// characters for group name. For example ABCDEFGHIJ.MS. We still need some characters left
+// for the actual semaphore names.
+#define MAX_APPLICATION_GROUP_ID_LENGTH 13
+#endif // __APPLE__
+
#ifdef __cplusplus
extern "C"
{
@@ -664,6 +678,11 @@ typedef enum _TimeConversionConstants
bool
ReadMemoryValueFromFile(const char* filename, size_t* val);
+#ifdef __APPLE__
+bool
+GetApplicationContainerFolder(PathCharString& buffer, const char *applicationGroupId, int applicationGroupIdLength);
+#endif // __APPLE__
+
/* This is duplicated in utilcode.h for CLR, with cooler type-traits */
template <typename T>
inline
diff --git a/src/pal/src/include/pal/process.h b/src/pal/src/include/pal/process.h
index f5d8b46de6..4eccc6189f 100644
--- a/src/pal/src/include/pal/process.h
+++ b/src/pal/src/include/pal/process.h
@@ -24,6 +24,7 @@ Revision History:
#define _PAL_PROCESS_H_
#include "pal/palinternal.h"
+#include "pal/stackstring.hpp"
#ifdef __cplusplus
extern "C"
@@ -43,6 +44,13 @@ extern DWORD gSID;
extern LPWSTR pAppDir;
+// The Mac sandbox application group ID (if exists) and container (shared) path
+#ifdef __APPLE__
+extern LPCSTR gApplicationGroupId;
+extern int gApplicationGroupIdLength;
+#endif // __APPLE__
+extern PathCharString *gSharedFilesPath;
+
/*++
Function:
PROCGetProcessIDFromHandle
diff --git a/src/pal/src/include/pal/sharedmemory.h b/src/pal/src/include/pal/sharedmemory.h
index fdc395e3c6..3ea3b71182 100644
--- a/src/pal/src/include/pal/sharedmemory.h
+++ b/src/pal/src/include/pal/sharedmemory.h
@@ -15,46 +15,45 @@
#define _countof(a) (sizeof(a) / sizeof(a[0]))
#endif // !_countof
-// The temporary folder is used for storing shared memory files and their lock files.
-// The location of the temporary folder varies (e.g. /data/local/tmp on Android)
-// and is set in TEMP_DIRECTORY_PATH. TEMP_DIRECTORY_PATH ends with '/'
+// The folder used for storing shared memory files and their lock files is defined in
+// the gSharedFilesPath global variable. The value of the variable depends on which
+// OS is being used, and if the application is running in a sandbox in Mac.
+// gSharedFilesPath ends with '/'
// - Global shared memory files go in:
-// {tmp}/.dotnet/shm/global/<fileName>
+// {gSharedFilesPath}/.dotnet/shm/global/<fileName>
// - Session-scoped shared memory files go in:
-// {tmp}/.dotnet/shm/session<sessionId>/<fileName>
+// {gSharedFilesPath}/.dotnet/shm/session<sessionId>/<fileName>
// - Lock files associated with global shared memory files go in:
-// {tmp}/.dotnet/lockfiles/global/<fileName>
+// {gSharedFilesPath}/.dotnet/lockfiles/global/<fileName>
// - Lock files associated with session-scoped shared memory files go in:
-// {tmp}/.dotnet/lockfiles/session<sessionId>/<fileName>
+// {gSharedFilesPath}/.dotnet/lockfiles/session<sessionId>/<fileName>
#define SHARED_MEMORY_MAX_FILE_NAME_CHAR_COUNT (_MAX_FNAME - 1)
-#define SHARED_MEMORY_MAX_NAME_CHAR_COUNT (_countof("Global\\") - 1 + SHARED_MEMORY_MAX_FILE_NAME_CHAR_COUNT)
+#define SHARED_MEMORY_MAX_NAME_CHAR_COUNT (string_countof("Global\\") + SHARED_MEMORY_MAX_FILE_NAME_CHAR_COUNT)
-#define SHARED_MEMORY_TEMP_DIRECTORY_PATH TEMP_DIRECTORY_PATH
-#define SHARED_MEMORY_RUNTIME_TEMP_DIRECTORY_PATH TEMP_DIRECTORY_PATH ".dotnet"
-
-#define SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_PATH TEMP_DIRECTORY_PATH ".dotnet/shm"
-#define SHARED_MEMORY_LOCK_FILES_DIRECTORY_PATH TEMP_DIRECTORY_PATH ".dotnet/lockfiles"
-static_assert_no_msg(_countof(SHARED_MEMORY_LOCK_FILES_DIRECTORY_PATH) >= _countof(SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_PATH));
+#define SHARED_MEMORY_RUNTIME_TEMP_DIRECTORY_NAME ".dotnet"
+#define SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_NAME ".dotnet/shm"
+#define SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME ".dotnet/lockfiles"
+static_assert_no_msg(_countof(SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME) >= _countof(SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_NAME));
#define SHARED_MEMORY_GLOBAL_DIRECTORY_NAME "global"
#define SHARED_MEMORY_SESSION_DIRECTORY_NAME_PREFIX "session"
static_assert_no_msg(_countof(SHARED_MEMORY_SESSION_DIRECTORY_NAME_PREFIX) >= _countof(SHARED_MEMORY_GLOBAL_DIRECTORY_NAME));
-#define SHARED_MEMORY_UNIQUE_TEMP_NAME_TEMPLATE TEMP_DIRECTORY_PATH ".coreclr.XXXXXX"
+#define SHARED_MEMORY_UNIQUE_TEMP_NAME_TEMPLATE ".coreclr.XXXXXX"
#define SHARED_MEMORY_MAX_SESSION_ID_CHAR_COUNT (10)
+// Note that this Max size does not include the prefix folder path size which is unknown (in the case of sandbox) until runtime
#define SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT \
( \
- _countof(SHARED_MEMORY_LOCK_FILES_DIRECTORY_PATH) - 1 + \
+ string_countof(SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME) + \
1 /* path separator */ + \
- _countof(SHARED_MEMORY_SESSION_DIRECTORY_NAME_PREFIX) - 1 + \
+ string_countof(SHARED_MEMORY_SESSION_DIRECTORY_NAME_PREFIX) + \
SHARED_MEMORY_MAX_SESSION_ID_CHAR_COUNT + \
1 /* path separator */ + \
SHARED_MEMORY_MAX_FILE_NAME_CHAR_COUNT \
)
-static_assert_no_msg(SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT + 1 /* null terminator */ <= MAX_LONGPATH);
class AutoFreeBuffer
{
@@ -107,9 +106,9 @@ public:
static void *Alloc(SIZE_T byteCount);
- template<SIZE_T DestinationByteCount, SIZE_T SourceByteCount> static SIZE_T CopyString(char (&destination)[DestinationByteCount], SIZE_T destinationStartOffset, const char (&source)[SourceByteCount]);
- template<SIZE_T DestinationByteCount> static SIZE_T CopyString(char (&destination)[DestinationByteCount], SIZE_T destinationStartOffset, LPCSTR source, SIZE_T sourceCharCount);
- template<SIZE_T DestinationByteCount> static SIZE_T AppendUInt32String(char (&destination)[DestinationByteCount], SIZE_T destinationStartOffset, UINT32 value);
+ template<SIZE_T SuffixByteCount> static void BuildSharedFilesPath(PathCharString& destination, const char (&suffix)[SuffixByteCount]);
+ static void BuildSharedFilesPath(PathCharString& destination, const char *suffix, int suffixByteCount);
+ static bool AppendUInt32String(PathCharString& destination, UINT32 value);
static bool EnsureDirectoryExists(const char *path, bool isGlobalLockAcquired, bool createIfNotExist = true, bool isSystemDirectory = false);
private:
@@ -126,6 +125,12 @@ public:
static bool TryAcquireFileLock(int fileDescriptor, int operation);
static void ReleaseFileLock(int fileDescriptor);
+
+ static void VerifyStringOperation(bool success);
+ static void VerifyStringOperation(BOOL success)
+ {
+ VerifyStringOperation(success != FALSE);
+ }
};
class SharedMemoryId
@@ -147,7 +152,7 @@ public:
bool Equals(SharedMemoryId *other) const;
public:
- SIZE_T AppendSessionDirectoryName(char (&path)[SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT + 1], SIZE_T pathCharCount) const;
+ bool AppendSessionDirectoryName(PathCharString& path) const;
};
enum class SharedMemoryType : UINT8
@@ -238,6 +243,9 @@ private:
static CRITICAL_SECTION s_creationDeletionProcessLock;
static int s_creationDeletionLockFileDescriptor;
+ static PathCharString* s_runtimeTempDirectoryPath;
+ static PathCharString* s_sharedMemoryDirectoryPath;
+
private:
static SharedMemoryProcessDataHeader *s_processDataHeaderListHead;
@@ -248,7 +256,7 @@ private:
#endif // _DEBUG
public:
- static void StaticInitialize();
+ static bool StaticInitialize();
static void StaticClose();
public:
@@ -257,6 +265,9 @@ public:
static void AcquireCreationDeletionFileLock();
static void ReleaseCreationDeletionFileLock();
+public:
+ static bool CopySharedMemoryBasePath(PathCharString& destination);
+
#ifdef _DEBUG
public:
static bool IsCreationDeletionProcessLockAcquired();
diff --git a/src/pal/src/include/pal/sharedmemory.inl b/src/pal/src/include/pal/sharedmemory.inl
index 69b8704b65..3a0c979781 100644
--- a/src/pal/src/include/pal/sharedmemory.inl
+++ b/src/pal/src/include/pal/sharedmemory.inl
@@ -11,43 +11,12 @@
#include <string.h>
-template<SIZE_T DestinationByteCount, SIZE_T SourceByteCount>
-SIZE_T SharedMemoryHelpers::CopyString(
- char (&destination)[DestinationByteCount],
- SIZE_T destinationStartOffset,
- const char(&source)[SourceByteCount])
+template<SIZE_T SuffixByteCount>
+void SharedMemoryHelpers::BuildSharedFilesPath(
+ PathCharString& destination,
+ const char (&suffix)[SuffixByteCount])
{
- return CopyString(destination, destinationStartOffset, source, SourceByteCount - 1);
-}
-
-template<SIZE_T DestinationByteCount>
-SIZE_T SharedMemoryHelpers::CopyString(
- char (&destination)[DestinationByteCount],
- SIZE_T destinationStartOffset,
- LPCSTR source,
- SIZE_T sourceCharCount)
-{
- _ASSERTE(destinationStartOffset < DestinationByteCount);
- _ASSERTE(sourceCharCount < DestinationByteCount - destinationStartOffset);
- _ASSERTE(strlen(source) == sourceCharCount);
-
- memcpy_s(&destination[destinationStartOffset], DestinationByteCount - destinationStartOffset, source, sourceCharCount + 1);
- return destinationStartOffset + sourceCharCount;
-}
-
-template<SIZE_T DestinationByteCount>
-SIZE_T SharedMemoryHelpers::AppendUInt32String(
- char (&destination)[DestinationByteCount],
- SIZE_T destinationStartOffset,
- UINT32 value)
-{
- _ASSERTE(destination != nullptr);
- _ASSERTE(destinationStartOffset < DestinationByteCount);
-
- int valueCharCount =
- sprintf_s(&destination[destinationStartOffset], DestinationByteCount - destinationStartOffset, "%u", value);
- _ASSERTE(valueCharCount > 0);
- return destinationStartOffset + valueCharCount;
+ BuildSharedFilesPath(destination, suffix, SuffixByteCount - 1);
}
#endif // !_PAL_SHARED_MEMORY_INL_
diff --git a/src/pal/src/include/pal/stackstring.hpp b/src/pal/src/include/pal/stackstring.hpp
index 1f18d5fe03..89fcd009b2 100644
--- a/src/pal/src/include/pal/stackstring.hpp
+++ b/src/pal/src/include/pal/stackstring.hpp
@@ -129,6 +129,12 @@ public:
return Set(s.m_buffer, s.m_count);
}
+ template<SIZE_T bufferLength> BOOL Set(const T (&buffer)[bufferLength])
+ {
+ // bufferLength includes terminator character
+ return Set(buffer, bufferLength - 1);
+ }
+
SIZE_T GetCount() const
{
return m_count;
@@ -157,6 +163,11 @@ public:
return result;
}
+ T * OpenStringBuffer()
+ {
+ return m_buffer;
+ }
+
//count should not include the terminating null
void CloseBuffer(SIZE_T count)
{
@@ -198,21 +209,38 @@ public:
{
return Append(s.GetString(), s.GetCount());
}
-
- BOOL IsEmpty()
- {
- return 0 == m_buffer[0];
- }
-
- void Clear()
- {
- m_count = 0;
- NullTerminate();
- }
- ~StackString()
- {
- DeleteBuffer();
- }
+
+ template<SIZE_T bufferLength> BOOL Append(const T (&buffer)[bufferLength])
+ {
+ // bufferLength includes terminator character
+ return Append(buffer, bufferLength - 1);
+ }
+
+ BOOL Append(T ch)
+ {
+ SIZE_T endpos = m_count;
+ if (!Resize(m_count + 1))
+ return FALSE;
+
+ m_buffer[endpos] = ch;
+ NullTerminate();
+ return TRUE;
+ }
+
+ BOOL IsEmpty()
+ {
+ return 0 == m_buffer[0];
+ }
+
+ void Clear()
+ {
+ m_count = 0;
+ NullTerminate();
+ }
+ ~StackString()
+ {
+ DeleteBuffer();
+ }
};
#if _DEBUG
diff --git a/src/pal/src/init/pal.cpp b/src/pal/src/init/pal.cpp
index dafe43df3a..294f458981 100644
--- a/src/pal/src/init/pal.cpp
+++ b/src/pal/src/init/pal.cpp
@@ -355,6 +355,52 @@ Initialize(
gPID = getpid();
gSID = getsid(gPID);
+ // The gSharedFilesPath is allocated dynamically so its destructor does not get
+ // called unexpectedly during cleanup
+ gSharedFilesPath = InternalNew<PathCharString>();
+ if (gSharedFilesPath == nullptr)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto done;
+ }
+
+#ifdef __APPLE__
+ // Store application group Id. It will be null if not set
+ gApplicationGroupId = getenv("DOTNET_SANDBOX_APPLICATION_GROUP_ID");
+
+ if (nullptr != gApplicationGroupId)
+ {
+ // Verify the length of the application group ID
+ gApplicationGroupIdLength = strlen(gApplicationGroupId);
+ if (gApplicationGroupIdLength > MAX_APPLICATION_GROUP_ID_LENGTH)
+ {
+ SetLastError(ERROR_BAD_LENGTH);
+ goto done;
+ }
+
+ // In sandbox, all IPC files (locks, pipes) should be written to the application group
+ // container. There will be no write permissions to TEMP_DIRECTORY_PATH
+ if (!GetApplicationContainerFolder(*gSharedFilesPath, gApplicationGroupId, gApplicationGroupIdLength))
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto done;
+ }
+
+ // Verify the size of the path won't exceed maximum allowed size
+ if (gSharedFilesPath->GetCount() + SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT + 1 /* null terminator */ > MAX_LONGPATH)
+ {
+ SetLastError(ERROR_FILENAME_EXCED_RANGE);
+ }
+ }
+ else
+#endif // __APPLE__
+ {
+ gSharedFilesPath->Set(TEMP_DIRECTORY_PATH);
+
+ // We can verify statically the non sandboxed case, since the size is known during compile time
+ static_assert_no_msg(string_countof(TEMP_DIRECTORY_PATH) + SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT + 1 /* null terminator */ <= MAX_LONGPATH);
+ }
+
fFirstTimeInit = true;
InitializeDefaultStackSize();
@@ -393,7 +439,11 @@ Initialize(
// we use large numbers of threads or have many open files.
}
- SharedMemoryManager::StaticInitialize();
+ if (!SharedMemoryManager::StaticInitialize())
+ {
+ ERROR("Shared memory static initialization failed!\n");
+ goto CLEANUP0;
+ }
/* initialize the shared memory infrastructure */
if (!SHMInitialize())
diff --git a/src/pal/src/sharedmemory/sharedmemory.cpp b/src/pal/src/sharedmemory/sharedmemory.cpp
index 46c07143a1..af3934aa61 100644
--- a/src/pal/src/sharedmemory/sharedmemory.cpp
+++ b/src/pal/src/sharedmemory/sharedmemory.cpp
@@ -9,6 +9,7 @@
#include "pal/malloc.hpp"
#include "pal/thread.hpp"
#include "pal/virtual.h"
+#include "pal/process.h"
#include <sys/file.h>
#include <sys/mman.h>
@@ -135,8 +136,10 @@ bool SharedMemoryHelpers::EnsureDirectoryExists(
return true;
}
- char tempPath[] = SHARED_MEMORY_UNIQUE_TEMP_NAME_TEMPLATE;
- if (mkdtemp(tempPath) == nullptr)
+ PathCharString tempPath;
+ BuildSharedFilesPath(tempPath, SHARED_MEMORY_UNIQUE_TEMP_NAME_TEMPLATE);
+
+ if (mkdtemp(tempPath.OpenStringBuffer()) == nullptr)
{
throw SharedMemoryException(static_cast<DWORD>(SharedMemoryError::IO));
}
@@ -164,7 +167,7 @@ bool SharedMemoryHelpers::EnsureDirectoryExists(
if (isSystemDirectory)
{
- // For system directories (such as SHARED_MEMORY_TEMP_DIRECTORY_PATH), require sufficient permissions only for the
+ // For system directories (such as TEMP_DIRECTORY_PATH), require sufficient permissions only for the
// current user. For instance, "docker run --mount ..." to mount /tmp to some directory on the host mounts the
// destination directory with the same permissions as the source directory, which may not include some permissions for
// other users. In the docker container, other user permissions are typically not relevant and relaxing the permissions
@@ -177,9 +180,9 @@ bool SharedMemoryHelpers::EnsureDirectoryExists(
throw SharedMemoryException(static_cast<DWORD>(SharedMemoryError::IO));
}
- // For non-system directories (such as SHARED_MEMORY_RUNTIME_TEMP_DIRECTORY_PATH), require sufficient permissions for all
- // users and try to update them if requested to create the directory, so that shared memory files may be shared by all
- // processes on the system.
+ // For non-system directories (such as gSharedFilesPath/SHARED_MEMORY_RUNTIME_TEMP_DIRECTORY_NAME),
+ // require sufficient permissions for all users and try to update them if requested to create the directory, so that
+ // shared memory files may be shared by all processes on the system.
if ((statInfo.st_mode & PermissionsMask_AllUsers_ReadWriteExecute) == PermissionsMask_AllUsers_ReadWriteExecute)
{
return true;
@@ -388,6 +391,34 @@ void SharedMemoryHelpers::ReleaseFileLock(int fileDescriptor)
} while (flockResult != 0 && errno == EINTR);
}
+void SharedMemoryHelpers::BuildSharedFilesPath(PathCharString& destination, const char *suffix, int suffixCharCount)
+{
+ _ASSERTE(strlen(suffix) == suffixCharCount);
+
+ VerifyStringOperation(destination.Set(*gSharedFilesPath));
+ VerifyStringOperation(destination.Append(suffix, suffixCharCount));
+}
+
+bool SharedMemoryHelpers::AppendUInt32String(
+ PathCharString& destination,
+ UINT32 value)
+{
+ char int32String[16];
+
+ int valueCharCount =
+ sprintf_s(int32String, sizeof(int32String), "%u", value);
+ _ASSERTE(valueCharCount > 0);
+ return destination.Append(int32String, valueCharCount) != FALSE;
+}
+
+void SharedMemoryHelpers::VerifyStringOperation(bool success)
+{
+ if (!success)
+ {
+ throw SharedMemoryException(static_cast<DWORD>(SharedMemoryError::OutOfMemory));
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SharedMemoryId
@@ -471,22 +502,17 @@ bool SharedMemoryId::Equals(SharedMemoryId *other) const
strcmp(GetName(), other->GetName()) == 0;
}
-SIZE_T SharedMemoryId::AppendSessionDirectoryName(
- char (&path)[SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT + 1],
- SIZE_T pathCharCount) const
+bool SharedMemoryId::AppendSessionDirectoryName(PathCharString& path) const
{
if (IsSessionScope())
{
- pathCharCount = SharedMemoryHelpers::CopyString(path, pathCharCount, SHARED_MEMORY_SESSION_DIRECTORY_NAME_PREFIX);
- pathCharCount = SharedMemoryHelpers::AppendUInt32String(path, pathCharCount, GetCurrentSessionId());
+ return path.Append(SHARED_MEMORY_SESSION_DIRECTORY_NAME_PREFIX) != FALSE
+ && SharedMemoryHelpers::AppendUInt32String(path, GetCurrentSessionId());
}
else
{
- pathCharCount = SharedMemoryHelpers::CopyString(path, pathCharCount, SHARED_MEMORY_GLOBAL_DIRECTORY_NAME);
+ return path.Append(SHARED_MEMORY_GLOBAL_DIRECTORY_NAME) != FALSE;
}
-
- _ASSERTE(pathCharCount <= SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT);
- return pathCharCount;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -538,12 +564,13 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen(
*createdRef = false;
}
+ PathCharString filePath;
SharedMemoryId id(name);
struct AutoCleanup
{
bool m_acquiredCreationDeletionFileLock;
- char *m_filePath;
+ PathCharString *m_filePath;
SIZE_T m_sessionDirectoryPathCharCount;
bool m_createdFile;
int m_fileDescriptor;
@@ -592,14 +619,14 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen(
if (m_createdFile)
{
_ASSERTE(m_filePath != nullptr);
- unlink(m_filePath);
+ unlink(*m_filePath);
}
if (m_sessionDirectoryPathCharCount != 0)
{
- _ASSERTE(m_filePath != nullptr);
- m_filePath[m_sessionDirectoryPathCharCount] = '\0';
- rmdir(m_filePath);
+ _ASSERTE(*m_filePath != nullptr);
+ m_filePath->CloseBuffer(m_sessionDirectoryPathCharCount);
+ rmdir(*m_filePath);
}
if (m_acquiredCreationDeletionFileLock)
@@ -623,21 +650,21 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen(
autoCleanup.m_acquiredCreationDeletionFileLock = true;
// Create the session directory
- char filePath[SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT + 1];
- SIZE_T filePathCharCount = SharedMemoryHelpers::CopyString(filePath, 0, SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_PATH);
- filePath[filePathCharCount++] = '/';
- filePathCharCount = id.AppendSessionDirectoryName(filePath, filePathCharCount);
+ SharedMemoryHelpers::VerifyStringOperation(SharedMemoryManager::CopySharedMemoryBasePath(filePath));
+ SharedMemoryHelpers::VerifyStringOperation(filePath.Append('/'));
+ SharedMemoryHelpers::VerifyStringOperation(id.AppendSessionDirectoryName(filePath));
if (!SharedMemoryHelpers::EnsureDirectoryExists(filePath, true /* isGlobalLockAcquired */, createIfNotExist))
{
_ASSERTE(!createIfNotExist);
return nullptr;
}
- autoCleanup.m_filePath = filePath;
- autoCleanup.m_sessionDirectoryPathCharCount = filePathCharCount;
+ autoCleanup.m_filePath = &filePath;
+ autoCleanup.m_sessionDirectoryPathCharCount = filePath.GetCount();
// Create or open the shared memory file
- filePath[filePathCharCount++] = '/';
- filePathCharCount = SharedMemoryHelpers::CopyString(filePath, filePathCharCount, id.GetName(), id.GetNameCharCount());
+ SharedMemoryHelpers::VerifyStringOperation(filePath.Append('/'));
+ SharedMemoryHelpers::VerifyStringOperation(filePath.Append(id.GetName(), id.GetNameCharCount()));
+
bool createdFile;
int fileDescriptor = SharedMemoryHelpers::CreateOrOpenFile(filePath, createIfNotExist, &createdFile);
if (fileDescriptor == -1)
@@ -919,16 +946,25 @@ void SharedMemoryProcessDataHeader::Close()
return;
}
- // Delete the shared memory file, and the session directory if it's not empty
- char path[SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT + 1];
- SIZE_T sessionDirectoryPathCharCount = SharedMemoryHelpers::CopyString(path, 0, SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_PATH);
- path[sessionDirectoryPathCharCount++] = '/';
- sessionDirectoryPathCharCount = m_id.AppendSessionDirectoryName(path, sessionDirectoryPathCharCount);
- path[sessionDirectoryPathCharCount++] = '/';
- SharedMemoryHelpers::CopyString(path, sessionDirectoryPathCharCount, m_id.GetName(), m_id.GetNameCharCount());
- unlink(path);
- path[sessionDirectoryPathCharCount] = '\0';
- rmdir(path);
+ try
+ {
+ // Delete the shared memory file, and the session directory if it's not empty
+ PathCharString path;
+ SharedMemoryHelpers::VerifyStringOperation(SharedMemoryManager::CopySharedMemoryBasePath(path));
+ SharedMemoryHelpers::VerifyStringOperation(path.Append('/'));
+ SharedMemoryHelpers::VerifyStringOperation(m_id.AppendSessionDirectoryName(path));
+ SharedMemoryHelpers::VerifyStringOperation(path.Append('/'));
+
+ SIZE_T sessionDirectoryPathCharCount = path.GetCount();
+ SharedMemoryHelpers::VerifyStringOperation(path.Append(m_id.GetName(), m_id.GetNameCharCount()));
+ unlink(path);
+ path.CloseBuffer(sessionDirectoryPathCharCount);
+ rmdir(path);
+ }
+ catch (SharedMemoryException)
+ {
+ // Ignore the error, just don't release shared data
+ }
}
SharedMemoryId *SharedMemoryProcessDataHeader::GetId()
@@ -998,15 +1034,36 @@ CRITICAL_SECTION SharedMemoryManager::s_creationDeletionProcessLock;
int SharedMemoryManager::s_creationDeletionLockFileDescriptor = -1;
SharedMemoryProcessDataHeader *SharedMemoryManager::s_processDataHeaderListHead = nullptr;
+PathCharString* SharedMemoryManager::s_runtimeTempDirectoryPath;
+PathCharString* SharedMemoryManager::s_sharedMemoryDirectoryPath;
#ifdef _DEBUG
SIZE_T SharedMemoryManager::s_creationDeletionProcessLockOwnerThreadId = SharedMemoryHelpers::InvalidThreadId;
SIZE_T SharedMemoryManager::s_creationDeletionFileLockOwnerThreadId = SharedMemoryHelpers::InvalidThreadId;
#endif // _DEBUG
-void SharedMemoryManager::StaticInitialize()
+bool SharedMemoryManager::StaticInitialize()
{
InitializeCriticalSection(&s_creationDeletionProcessLock);
+
+ s_runtimeTempDirectoryPath = InternalNew<PathCharString>();
+ s_sharedMemoryDirectoryPath = InternalNew<PathCharString>();
+
+ if (s_runtimeTempDirectoryPath && s_sharedMemoryDirectoryPath)
+ {
+ try
+ {
+ SharedMemoryHelpers::BuildSharedFilesPath(*s_runtimeTempDirectoryPath, SHARED_MEMORY_RUNTIME_TEMP_DIRECTORY_NAME);
+ SharedMemoryHelpers::BuildSharedFilesPath(*s_sharedMemoryDirectoryPath, SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_NAME);
+
+ return true;
+ }
+ catch (SharedMemoryException)
+ {
+ // Ignore and let function fail
+ }
+ }
+ return false;
}
void SharedMemoryManager::StaticClose()
@@ -1056,7 +1113,7 @@ void SharedMemoryManager::AcquireCreationDeletionFileLock()
if (s_creationDeletionLockFileDescriptor == -1)
{
if (!SharedMemoryHelpers::EnsureDirectoryExists(
- SHARED_MEMORY_TEMP_DIRECTORY_PATH,
+ *gSharedFilesPath,
false /* isGlobalLockAcquired */,
false /* createIfNotExist */,
true /* isSystemDirectory */))
@@ -1064,12 +1121,12 @@ void SharedMemoryManager::AcquireCreationDeletionFileLock()
throw SharedMemoryException(static_cast<DWORD>(SharedMemoryError::IO));
}
SharedMemoryHelpers::EnsureDirectoryExists(
- SHARED_MEMORY_RUNTIME_TEMP_DIRECTORY_PATH,
+ *s_runtimeTempDirectoryPath,
false /* isGlobalLockAcquired */);
SharedMemoryHelpers::EnsureDirectoryExists(
- SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_PATH,
+ *s_sharedMemoryDirectoryPath,
false /* isGlobalLockAcquired */);
- s_creationDeletionLockFileDescriptor = SharedMemoryHelpers::OpenDirectory(SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_PATH);
+ s_creationDeletionLockFileDescriptor = SharedMemoryHelpers::OpenDirectory(*s_sharedMemoryDirectoryPath);
if (s_creationDeletionLockFileDescriptor == -1)
{
throw SharedMemoryException(static_cast<DWORD>(SharedMemoryError::IO));
@@ -1161,3 +1218,8 @@ SharedMemoryProcessDataHeader *SharedMemoryManager::FindProcessDataHeader(Shared
}
return nullptr;
}
+
+bool SharedMemoryManager::CopySharedMemoryBasePath(PathCharString& destination)
+{
+ return destination.Set(*s_sharedMemoryDirectoryPath) != FALSE;
+}
diff --git a/src/pal/src/synchobj/mutex.cpp b/src/pal/src/synchobj/mutex.cpp
index bbc3e2d083..a018d9db84 100644
--- a/src/pal/src/synchobj/mutex.cpp
+++ b/src/pal/src/synchobj/mutex.cpp
@@ -1069,13 +1069,17 @@ SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen(
_ASSERTE(name != nullptr);
_ASSERTE(createIfNotExist || !acquireLockIfCreated);
+#if !NAMED_MUTEX_USE_PTHREAD_MUTEX
+ PathCharString lockFilePath;
+#endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX
+
struct AutoCleanup
{
bool m_acquiredCreationDeletionProcessLock;
bool m_acquiredCreationDeletionFileLock;
SharedMemoryProcessDataHeader *m_processDataHeader;
#if !NAMED_MUTEX_USE_PTHREAD_MUTEX
- char *m_lockFilePath;
+ PathCharString *m_lockFilePath;
SIZE_T m_sessionDirectoryPathCharCount;
bool m_createdLockFile;
int m_lockFileDescriptor;
@@ -1109,14 +1113,14 @@ SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen(
if (m_createdLockFile)
{
_ASSERTE(m_lockFilePath != nullptr);
- unlink(m_lockFilePath);
+ unlink(*m_lockFilePath);
}
if (m_sessionDirectoryPathCharCount != 0)
{
_ASSERTE(m_lockFilePath != nullptr);
- m_lockFilePath[m_sessionDirectoryPathCharCount] = '\0';
- rmdir(m_lockFilePath);
+ m_lockFilePath->CloseBuffer(m_sessionDirectoryPathCharCount);
+ rmdir(*m_lockFilePath);
}
}
#endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX
@@ -1179,29 +1183,26 @@ SharedMemoryProcessDataHeader *NamedMutexProcessData::CreateOrOpen(
{
#if !NAMED_MUTEX_USE_PTHREAD_MUTEX
// Create the lock files directory
- char lockFilePath[SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT + 1];
- SIZE_T lockFilePathCharCount =
- SharedMemoryHelpers::CopyString(lockFilePath, 0, SHARED_MEMORY_LOCK_FILES_DIRECTORY_PATH);
+ SharedMemoryHelpers::BuildSharedFilesPath(lockFilePath, SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME);
if (created)
{
SharedMemoryHelpers::EnsureDirectoryExists(lockFilePath, true /* isGlobalLockAcquired */);
}
// Create the session directory
- lockFilePath[lockFilePathCharCount++] = '/';
SharedMemoryId *id = processDataHeader->GetId();
- lockFilePathCharCount = id->AppendSessionDirectoryName(lockFilePath, lockFilePathCharCount);
+ SharedMemoryHelpers::VerifyStringOperation(lockFilePath.Append('/'));
+ SharedMemoryHelpers::VerifyStringOperation(id->AppendSessionDirectoryName(lockFilePath));
if (created)
{
SharedMemoryHelpers::EnsureDirectoryExists(lockFilePath, true /* isGlobalLockAcquired */);
- autoCleanup.m_lockFilePath = lockFilePath;
- autoCleanup.m_sessionDirectoryPathCharCount = lockFilePathCharCount;
+ autoCleanup.m_lockFilePath = &lockFilePath;
+ autoCleanup.m_sessionDirectoryPathCharCount = lockFilePath.GetCount();
}
// Create or open the lock file
- lockFilePath[lockFilePathCharCount++] = '/';
- lockFilePathCharCount =
- SharedMemoryHelpers::CopyString(lockFilePath, lockFilePathCharCount, id->GetName(), id->GetNameCharCount());
+ SharedMemoryHelpers::VerifyStringOperation(lockFilePath.Append('/'));
+ SharedMemoryHelpers::VerifyStringOperation(lockFilePath.Append(id->GetName(), id->GetNameCharCount()));
int lockFileDescriptor = SharedMemoryHelpers::CreateOrOpenFile(lockFilePath, created);
if (lockFileDescriptor == -1)
{
@@ -1316,17 +1317,25 @@ void NamedMutexProcessData::Close(bool isAbruptShutdown, bool releaseSharedData)
return;
}
- // Delete the lock file, and the session directory if it's not empty
- char path[SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT + 1];
- SIZE_T sessionDirectoryPathCharCount = SharedMemoryHelpers::CopyString(path, 0, SHARED_MEMORY_LOCK_FILES_DIRECTORY_PATH);
- path[sessionDirectoryPathCharCount++] = '/';
- SharedMemoryId *id = m_processDataHeader->GetId();
- sessionDirectoryPathCharCount = id->AppendSessionDirectoryName(path, sessionDirectoryPathCharCount);
- path[sessionDirectoryPathCharCount++] = '/';
- SharedMemoryHelpers::CopyString(path, sessionDirectoryPathCharCount, id->GetName(), id->GetNameCharCount());
- unlink(path);
- path[sessionDirectoryPathCharCount] = '\0';
- rmdir(path);
+ try
+ {
+ // Delete the lock file, and the session directory if it's not empty
+ PathCharString path;
+ SharedMemoryHelpers::BuildSharedFilesPath(path, SHARED_MEMORY_LOCK_FILES_DIRECTORY_NAME);
+ SharedMemoryId *id = m_processDataHeader->GetId();
+ SharedMemoryHelpers::VerifyStringOperation(path.Append('/'));
+ SharedMemoryHelpers::VerifyStringOperation(id->AppendSessionDirectoryName(path));
+ SharedMemoryHelpers::VerifyStringOperation(path.Append('/'));
+ SIZE_T sessionDirectoryPathCharCount = path.GetCount();
+ SharedMemoryHelpers::VerifyStringOperation(path.Append(id->GetName(), id->GetNameCharCount()));
+ unlink(path);
+ path.CloseBuffer(sessionDirectoryPathCharCount);
+ rmdir(path);
+ }
+ catch (SharedMemoryException)
+ {
+ // Ignore the error, just don't release shared data
+ }
#endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX
}
diff --git a/src/pal/src/thread/process.cpp b/src/pal/src/thread/process.cpp
index 19d3c08fc0..0141b07654 100644
--- a/src/pal/src/thread/process.cpp
+++ b/src/pal/src/thread/process.cpp
@@ -139,6 +139,13 @@ Volatile<LONG> terminator = 0;
DWORD gPID = (DWORD) -1;
DWORD gSID = (DWORD) -1;
+// Application group ID for this process
+#ifdef __APPLE__
+LPCSTR gApplicationGroupId = nullptr;
+int gApplicationGroupIdLength = 0;
+#endif // __APPLE__
+PathCharString* gSharedFilesPath = nullptr;
+
// The lowest common supported semaphore length, including null character
// NetBSD-7.99.25: 15 characters
// MacOSX 10.11: 31 -- Core 1.0 RC2 compatibility
@@ -1983,6 +1990,15 @@ exit:
return launched;
}
+#ifdef __APPLE__
+LPCSTR
+PALAPI
+PAL_GetApplicationGroupId()
+{
+ return gApplicationGroupId;
+}
+#endif // __APPLE__
+
/*++
Function:
GetProcessIdDisambiguationKey
@@ -3945,6 +3961,21 @@ PROCGetProcessStatusExit:
return palError;
}
+#ifdef __APPLE__
+bool GetApplicationContainerFolder(PathCharString& buffer, const char *applicationGroupId, int applicationGroupIdLength)
+{
+ const char *homeDir = getpwuid(getuid())->pw_dir;
+ int homeDirLength = strlen(homeDir);
+
+ // The application group container folder is defined as:
+ // /user/{loginname}/Library/Group Containers/{AppGroupId}/
+ return buffer.Set(homeDir, homeDirLength)
+ && buffer.Append(APPLICATION_CONTAINER_BASE_PATH_SUFFIX)
+ && buffer.Append(applicationGroupId, applicationGroupIdLength)
+ && buffer.Append('/');
+}
+#endif // __APPLE__
+
#ifdef _DEBUG
void PROCDumpThreadList()
{