Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a no-cache backed CLRConfig lookup mechanism #59513

Merged
5 changes: 1 addition & 4 deletions src/coreclr/inc/clrconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,7 @@ class CLRConfig
static HRESULT GetConfigValue(const ConfigStringInfo & info, __deref_out_z LPWSTR * outVal);

//
// Check whether an option is specified (e.g. explicitly listed) in any of the CLRConfig
// locations: environment or registry (with or without COMPlus_) or any config file.
// The result is therefore a conservative approximation (some settings do not actually
// take effect everywhere and no setting is valid both with and without COMPlus_)
// Check whether an option is specified (e.g. explicitly listed) in the CLRConfig.
//
static BOOL IsConfigOptionSpecified(LPCWSTR name);

Expand Down
94 changes: 94 additions & 0 deletions src/coreclr/inc/clrconfignocache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
//
// --------------------------------------------------------------------------------------------------
// clrconfignocache.h
//
// Logic for resolving configuration names.
//

#ifndef StrLen
#define StrLen(STR) ((sizeof(STR) / sizeof(STR[0])) - 1)
#endif // !StrLen

// Config prefixes
#define COMPLUS_PREFIX_A "COMPlus_"
#define COMPLUS_PREFIX W("COMPlus_")
#define LEN_OF_COMPLUS_PREFIX StrLen(COMPLUS_PREFIX_A)

#define DOTNET_PREFIX_A "DOTNET_"
#define DOTNET_PREFIX W("DOTNET_")
#define LEN_OF_DOTNET_PREFIX StrLen(DOTNET_PREFIX_A)

class CLRConfigNoCache
{
const char* _value;

CLRConfigNoCache() = default;
CLRConfigNoCache(LPCSTR cfg) : _value { cfg }
{ }

public:
bool IsSet() const { return _value != NULL; }

LPCSTR AsString() const
{
_ASSERTE(IsSet());
return _value;
}

bool TryAsInteger(int radix, DWORD& result) const
{
_ASSERTE(IsSet());

errno = 0;
LPSTR endPtr;
result = strtoul(_value, &endPtr, radix);
bool fSuccess = (errno != ERANGE) && (endPtr != _value);
return fSuccess;
}

static CLRConfigNoCache Get(LPCSTR cfg, bool noPrefix = false, char*(*getEnvFptr)(const char*) = nullptr)
{
char nameBuffer[64];
const char* fallbackPrefix = NULL;
const size_t namelen = strlen(cfg);

if (noPrefix)
{
if (namelen >= _countof(nameBuffer))
{
_ASSERTE(!"Environment variable name too long.");
return {};
}

*nameBuffer = W('\0');
}
else
{
bool dotnetValid = namelen < (size_t)(_countof(nameBuffer) - 1 - LEN_OF_DOTNET_PREFIX);
bool complusValid = namelen < (size_t)(_countof(nameBuffer) - 1 - LEN_OF_COMPLUS_PREFIX);
if (!dotnetValid || !complusValid)
{
_ASSERTE(!"Environment variable name too long.");
return {};
}

// Priority order is DOTNET_ and then COMPlus_.
strcpy_s(nameBuffer, _countof(nameBuffer), DOTNET_PREFIX_A);
fallbackPrefix = COMPLUS_PREFIX_A;
}

strcat_s(nameBuffer, _countof(nameBuffer), cfg);

LPCSTR val = getEnvFptr != NULL ? getEnvFptr(nameBuffer) : getenv(nameBuffer);
if (val == NULL && fallbackPrefix != NULL)
{
strcpy_s(nameBuffer, _countof(nameBuffer), fallbackPrefix);
strcat_s(nameBuffer, _countof(nameBuffer), cfg);
val = getEnvFptr != NULL ? getEnvFptr(nameBuffer) : getenv(nameBuffer);
}

return { val };
}
};
5 changes: 5 additions & 0 deletions src/coreclr/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,11 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeCircularMB, W("EventPipeCircularMB"),
RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeProcNumbers, W("EventPipeProcNumbers"), 0, "Enable/disable capturing processor numbers in EventPipe event headers")
RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeOutputStreaming, W("EventPipeOutputStreaming"), 0, "Enable/disable streaming for trace file set in COMPlus_EventPipeOutputPath. Non-zero values enable streaming.")

#ifdef FEATURE_AUTO_TRACE
RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_AutoTrace_N_Tracers, W("AutoTrace_N_Tracers"), 0, "", CLRConfig::LookupOptions::ParseIntegerAsBase10)
RETAIL_CONFIG_STRING_INFO(INTERNAL_AutoTrace_Command, W("AutoTrace_Command"), "")
#endif // FEATURE_AUTO_TRACE

//
// Generational Aware Analysis
//
Expand Down
6 changes: 0 additions & 6 deletions src/coreclr/inc/cor.h
Original file line number Diff line number Diff line change
Expand Up @@ -1634,12 +1634,6 @@ DECLARE_INTERFACE_(IMetaDataInfo, IUnknown)
// Native Link method custom value definitions. This is for N-direct support.
//

#define COR_NATIVE_LINK_CUSTOM_VALUE L"COMPLUS_NativeLink"
#define COR_NATIVE_LINK_CUSTOM_VALUE_ANSI "COMPLUS_NativeLink"

// count of chars for COR_NATIVE_LINK_CUSTOM_VALUE(_ANSI)
#define COR_NATIVE_LINK_CUSTOM_VALUE_CC 18

#include <pshpack1.h>
typedef struct
{
Expand Down
12 changes: 10 additions & 2 deletions src/coreclr/pal/src/exception/signal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do

#include "pal/palinternal.h"

#include <clrconfignocache.h>

#include <errno.h>
#include <signal.h>

Expand Down Expand Up @@ -145,9 +147,15 @@ BOOL SEHInitializeSignals(CorUnix::CPalThread *pthrCurrent, DWORD flags)
TRACE("Initializing signal handlers %04x\n", flags);

#if !HAVE_MACH_EXCEPTIONS
char* enableAlternateStackCheck = getenv("COMPlus_EnableAlternateStackCheck");
g_enable_alternate_stack_check = false;

g_enable_alternate_stack_check = enableAlternateStackCheck && (strtoul(enableAlternateStackCheck, NULL, 10) != 0);
CLRConfigNoCache stackCheck = CLRConfigNoCache::Get("EnableAlternateStackCheck", /*noprefix*/ false, &getenv);
if (stackCheck.IsSet())
{
DWORD value;
if (stackCheck.TryAsInteger(10, value))
g_enable_alternate_stack_check = (value != 0);
}
#endif

if (flags & PAL_INITIALIZE_REGISTER_SIGNALS)
Expand Down
27 changes: 10 additions & 17 deletions src/coreclr/pal/src/init/pal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ int CacheLineSize;
#endif

#include <algorithm>
#include <clrconfignocache.h>

using namespace CorUnix;

Expand Down Expand Up @@ -268,17 +269,13 @@ EnsureStackSize(SIZE_T stackSize)
void
InitializeDefaultStackSize()
{
char* defaultStackSizeStr = getenv("COMPlus_DefaultStackSize");
if (defaultStackSizeStr != NULL)
CLRConfigNoCache defStackSize = CLRConfigNoCache::Get("DefaultStackSize", /*noprefix*/ false, &getenv);
if (defStackSize.IsSet())
{
errno = 0;
// Like all numeric values specific by the COMPlus_xxx variables, it is a
// hexadecimal string without any prefix.
long int size = strtol(defaultStackSizeStr, NULL, 16);

if (errno == 0)
DWORD size;
if (defStackSize.TryAsInteger(16, size))
{
g_defaultStackSize = std::max(size, (long int)PTHREAD_STACK_MIN);
g_defaultStackSize = std::max(size, (DWORD)PTHREAD_STACK_MIN);
}
}

Expand Down Expand Up @@ -406,15 +403,11 @@ Initialize(
#endif // ENSURE_PRIMARY_STACK_SIZE

#ifdef FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION
char* useDefaultBaseAddr = getenv("COMPlus_UseDefaultBaseAddr");
if (useDefaultBaseAddr != NULL)
CLRConfigNoCache useDefaultBaseAddr = CLRConfigNoCache::Get("UseDefaultBaseAddr", /*noprefix*/ false, &getenv);
if (useDefaultBaseAddr.IsSet())
{
errno = 0;
// Like all numeric values specific by the COMPlus_xxx variables, it is a
// hexadecimal string without any prefix.
long int flag = strtol(useDefaultBaseAddr, NULL, 16);

if (errno == 0)
DWORD flag;
if (useDefaultBaseAddr.TryAsInteger(16, flag))
{
g_useDefaultBaseAddr = (BOOL) flag;
}
Expand Down
12 changes: 9 additions & 3 deletions src/coreclr/pal/src/misc/tracepointprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ Revision History:

SET_DEFAULT_DEBUG_CHANNEL(MISC);

// clrconfignocache.h uses macro _ASSERTE, which needd to use variable
// defdbgchan defined by SET_DEFAULT_DEBUG_CHANNEL.
#include <clrconfignocache.h>

/*++

Initialization logic for LTTng tracepoint providers.
Expand Down Expand Up @@ -62,10 +66,12 @@ PAL_InitializeTracing(void)
// Check if loading the LTTng providers should be disabled.
// Note: this env var is formally declared in clrconfigvalues.h, but
// this code is executed too early to use the mechanics that come with that definition.
char *disableValue = getenv("COMPlus_LTTng");
if (disableValue != NULL)
CLRConfigNoCache cfgLTTng = CLRConfigNoCache::Get("LTTng", /*noprefix*/ false, &getenv);
if (cfgLTTng.IsSet())
{
fShouldLoad = strtol(disableValue, NULL, 10);
DWORD value;
if (cfgLTTng.TryAsInteger(10, value))
fShouldLoad = (int)value;
}

// Get the path to the currently executing shared object (libcoreclr.so).
Expand Down
80 changes: 46 additions & 34 deletions src/coreclr/pal/src/thread/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ SET_DEFAULT_DEBUG_CHANNEL(PROCESS); // some headers have code with asserts, so d
#include "pal/stackstring.hpp"
#include "pal/signal.hpp"

#include <clrconfignocache.h>

#include <errno.h>
#if HAVE_POLL
#include <poll.h>
Expand Down Expand Up @@ -3108,6 +3110,8 @@ PROCFormatInt(ULONG32 value)
return buffer;
}

static const INT UndefinedDumpType = 0;

/*++
Function
PROCBuildCreateDumpCommandLine
Expand All @@ -3124,8 +3128,8 @@ PROCBuildCreateDumpCommandLine(
std::vector<const char*>& argv,
char** pprogram,
char** ppidarg,
char* dumpName,
char* dumpType,
const char* dumpName,
INT dumpType,
BOOL diag,
BOOL crashReport)
{
Expand Down Expand Up @@ -3170,24 +3174,19 @@ PROCBuildCreateDumpCommandLine(
argv.push_back(dumpName);
}

if (dumpType != nullptr)
switch (dumpType)
{
if (strcmp(dumpType, "1") == 0)
{
argv.push_back("--normal");
}
else if (strcmp(dumpType, "2") == 0)
{
argv.push_back("--withheap");
}
else if (strcmp(dumpType, "3") == 0)
{
argv.push_back("--triage");
}
else if (strcmp(dumpType, "4") == 0)
{
argv.push_back("--full");
}
case 1: argv.push_back("--normal");
break;
case 2: argv.push_back("--withheap");
break;
case 3: argv.push_back("--triage");
break;
case 4: argv.push_back("--full");
break;
case UndefinedDumpType:
default:
break;
}

if (diag)
Expand Down Expand Up @@ -3277,19 +3276,37 @@ Return
BOOL
PROCAbortInitialize()
{
char* enabled = getenv("COMPlus_DbgEnableMiniDump");
if (enabled != nullptr && _stricmp(enabled, "1") == 0)
CLRConfigNoCache enabledCfg= CLRConfigNoCache::Get("DbgEnableMiniDump", /*noprefix*/ false, &getenv);

DWORD enabled = 0;
if (enabledCfg.IsSet()
&& enabledCfg.TryAsInteger(10, enabled)
&& enabled)
{
char* dumpName = getenv("COMPlus_DbgMiniDumpName");
char* dumpType = getenv("COMPlus_DbgMiniDumpType");
char* diagStr = getenv("COMPlus_CreateDumpDiagnostics");
BOOL diag = diagStr != nullptr && strcmp(diagStr, "1") == 0;
char* crashReportStr = getenv("COMPlus_EnableCrashReport");
BOOL crashReport = crashReportStr != nullptr && strcmp(crashReportStr, "1") == 0;
CLRConfigNoCache dmpNameCfg = CLRConfigNoCache::Get("DbgMiniDumpName", /*noprefix*/ false, &getenv);

CLRConfigNoCache dmpTypeCfg = CLRConfigNoCache::Get("DbgMiniDumpType", /*noprefix*/ false, &getenv);
DWORD dumpType = UndefinedDumpType;
if (dmpTypeCfg.IsSet())
{
(void)dmpTypeCfg.TryAsInteger(10, dumpType);
if (dumpType < 1 || dumpType > 4)
{
dumpType = UndefinedDumpType;
}
}

CLRConfigNoCache createDumpCfg = CLRConfigNoCache::Get("CreateDumpDiagnostics", /*noprefix*/ false, &getenv);
DWORD val = 0;
BOOL diag = createDumpCfg.IsSet() && createDumpCfg.TryAsInteger(10, val) && val == 1;

CLRConfigNoCache enabldReportCfg = CLRConfigNoCache::Get("EnableCrashReport", /*noprefix*/ false, &getenv);
val = 0;
BOOL crashReport = enabldReportCfg.IsSet() && enabldReportCfg.TryAsInteger(10, val) && val == 1;

char* program = nullptr;
char* pidarg = nullptr;
if (!PROCBuildCreateDumpCommandLine(g_argvCreateDump, &program, &pidarg, dumpName, dumpType, diag, crashReport))
if (!PROCBuildCreateDumpCommandLine(g_argvCreateDump, &program, &pidarg, dmpNameCfg.AsString(), dumpType, diag, crashReport))
{
return FALSE;
}
Expand Down Expand Up @@ -3325,23 +3342,18 @@ PAL_GenerateCoreDump(
BOOL diag)
{
std::vector<const char*> argvCreateDump;
char dumpTypeStr[16];

if (dumpType < 1 || dumpType > 4)
{
return FALSE;
}
if (_itoa_s(dumpType, dumpTypeStr, sizeof(dumpTypeStr), 10) != 0)
{
return FALSE;
}
if (dumpName != nullptr && dumpName[0] == '\0')
{
dumpName = nullptr;
}
char* program = nullptr;
char* pidarg = nullptr;
BOOL result = PROCBuildCreateDumpCommandLine(argvCreateDump, &program, &pidarg, (char*)dumpName, dumpTypeStr, diag, false);
BOOL result = PROCBuildCreateDumpCommandLine(argvCreateDump, &program, &pidarg, dumpName, dumpType, diag, false);
if (result)
{
result = PROCCreateCrashDump(argvCreateDump);
Expand Down
Loading