Skip to content
Merged
Changes from 5 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
124 changes: 79 additions & 45 deletions src/coreclr/pal/src/thread/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ SET_DEFAULT_DEBUG_CHANNEL(PROCESS); // some headers have code with asserts, so d
#include <stdint.h>
#include <dlfcn.h>
#include <limits.h>
#include <vector>

#ifdef __linux__
#include <linux/membarrier.h>
Expand Down Expand Up @@ -197,7 +196,8 @@ Volatile<PSHUTDOWN_CALLBACK> g_shutdownCallback = nullptr;
Volatile<PCREATEDUMP_CALLBACK> g_createdumpCallback = nullptr;

// Crash dump generating program arguments. Initialized in PROCAbortInitialize().
std::vector<const char*> g_argvCreateDump;
#define MAX_ARGV_ENTRIES 32
const char* g_argvCreateDump[MAX_ARGV_ENTRIES] = { nullptr };

//
// Key used for associating CPalThread's with the underlying pthread
Expand Down Expand Up @@ -2282,7 +2282,7 @@ Return
--*/
BOOL
PROCBuildCreateDumpCommandLine(
std::vector<const char*>& argv,
const char* argv[],
char** pprogram,
char** ppidarg,
const char* dumpName,
Expand Down Expand Up @@ -2323,65 +2323,80 @@ PROCBuildCreateDumpCommandLine(
{
return FALSE;
}
argv.push_back(program);

int argc = 0;
if (argc + 1 >= MAX_ARGV_ENTRIES) return FALSE; // Need room for program and null terminator
argv[argc++] = program;

if (dumpName != nullptr)
{
argv.push_back("--name");
argv.push_back(dumpName);
if (argc + 3 >= MAX_ARGV_ENTRIES) return FALSE; // Need room for --name, dumpName, and null terminator
argv[argc++] = "--name";
argv[argc++] = dumpName;
}

switch (dumpType)
{
case DumpTypeNormal:
argv.push_back("--normal");
if (argc + 2 >= MAX_ARGV_ENTRIES) return FALSE; // Need room for --normal and null terminator
argv[argc++] = "--normal";
break;
case DumpTypeWithHeap:
argv.push_back("--withheap");
if (argc + 2 >= MAX_ARGV_ENTRIES) return FALSE; // Need room for --withheap and null terminator
argv[argc++] = "--withheap";
break;
case DumpTypeTriage:
argv.push_back("--triage");
if (argc + 2 >= MAX_ARGV_ENTRIES) return FALSE; // Need room for --triage and null terminator
argv[argc++] = "--triage";
break;
case DumpTypeFull:
argv.push_back("--full");
if (argc + 2 >= MAX_ARGV_ENTRIES) return FALSE; // Need room for --full and null terminator
argv[argc++] = "--full";
break;
default:
break;
}

if (flags & GenerateDumpFlagsLoggingEnabled)
{
argv.push_back("--diag");
if (argc + 2 >= MAX_ARGV_ENTRIES) return FALSE; // Need room for --diag and null terminator
argv[argc++] = "--diag";
}

if (flags & GenerateDumpFlagsVerboseLoggingEnabled)
{
argv.push_back("--verbose");
if (argc + 2 >= MAX_ARGV_ENTRIES) return FALSE; // Need room for --verbose and null terminator
argv[argc++] = "--verbose";
}

if (flags & GenerateDumpFlagsCrashReportEnabled)
{
argv.push_back("--crashreport");
if (argc + 2 >= MAX_ARGV_ENTRIES) return FALSE; // Need room for --crashreport and null terminator
argv[argc++] = "--crashreport";
}

if (flags & GenerateDumpFlagsCrashReportOnlyEnabled)
{
argv.push_back("--crashreportonly");
if (argc + 2 >= MAX_ARGV_ENTRIES) return FALSE; // Need room for --crashreportonly and null terminator
argv[argc++] = "--crashreportonly";
}

if (g_running_in_exe)
{
argv.push_back("--singlefile");
if (argc + 2 >= MAX_ARGV_ENTRIES) return FALSE; // Need room for --singlefile and null terminator
argv[argc++] = "--singlefile";
}

if (logFileName != nullptr)
{
argv.push_back("--logtofile");
argv.push_back(logFileName);
if (argc + 3 >= MAX_ARGV_ENTRIES) return FALSE; // Need room for --logtofile, logFileName, and null terminator
argv[argc++] = "--logtofile";
argv[argc++] = logFileName;
}

argv.push_back(*ppidarg);
argv.push_back(nullptr);
if (argc + 2 >= MAX_ARGV_ENTRIES) return FALSE; // Need room for pidarg and null terminator
argv[argc++] = *ppidarg;
argv[argc++] = nullptr;

return TRUE;
}
Expand All @@ -2399,15 +2414,15 @@ PROCBuildCreateDumpCommandLine(
--*/
BOOL
PROCCreateCrashDump(
std::vector<const char*>& argv,
const char* argv[],
LPSTR errorMessageBuffer,
INT cbErrorMessageBuffer,
bool serialize)
{
#if defined(TARGET_IOS) || defined(TARGET_TVOS)
return FALSE;
#else
_ASSERTE(argv.size() > 0);
_ASSERTE(argv[0] != nullptr);
_ASSERTE(errorMessageBuffer == nullptr || cbErrorMessageBuffer > 0);

if (serialize)
Expand Down Expand Up @@ -2494,7 +2509,12 @@ PROCCreateCrashDump(
SEHCleanupSignals(true /* isChildProcess */);

// Call the statically linked createdump code
callbackResult = g_createdumpCallback(argv.size(), argv.data());
int argc = 0;
while (argv[argc] != nullptr && argc < MAX_ARGV_ENTRIES)
{
argc++;
}
callbackResult = g_createdumpCallback(argc, argv);
// Set the shutdown callback to nullptr and exit
// If we don't exit, the child's execution will continue into the diagnostic server behavior
// which causes all sorts of problems.
Expand All @@ -2504,7 +2524,7 @@ PROCCreateCrashDump(
else
{
// Execute the createdump program
if (execve(argv[0], (char**)argv.data(), palEnvironment) == -1)
if (execve(argv[0], (char**)argv, palEnvironment) == -1)
{
fprintf(stderr, "Problem launching createdump (may not have execute permissions): execve(%s) FAILED %s (%d)\n", argv[0], strerror(errno), errno);
exit(-1);
Expand Down Expand Up @@ -2682,7 +2702,7 @@ PAL_GenerateCoreDump(
LPSTR errorMessageBuffer,
INT cbErrorMessageBuffer)
{
std::vector<const char*> argvCreateDump;
const char* argvCreateDump[MAX_ARGV_ENTRIES] = { nullptr };

if (dumpType <= DumpTypeUnknown || dumpType > DumpTypeMax)
{
Expand Down Expand Up @@ -2748,59 +2768,73 @@ PROCCreateCrashDumpIfEnabled(int signal, siginfo_t* siginfo, void* context, bool
DoNotOptimize(&context);

// If enabled, launch the create minidump utility and wait until it completes
if (!g_argvCreateDump.empty())
if (g_argvCreateDump[0] != nullptr)
{
std::vector<const char*> argv(g_argvCreateDump);
const char* argv[MAX_ARGV_ENTRIES];
char* signalArg = nullptr;
char* crashThreadArg = nullptr;
char* signalCodeArg = nullptr;
char* signalErrnoArg = nullptr;
char* signalAddressArg = nullptr;

if (signal != 0)
// Copy the createdump argv
int argc = 0;
for (; argc < MAX_ARGV_ENTRIES && g_argvCreateDump[argc] != nullptr; argc++)
{
// Remove the terminating nullptr
argv.pop_back();
argv[argc] = g_argvCreateDump[argc];
}

if (signal != 0 && argc + 3 < MAX_ARGV_ENTRIES) // Need room for at least --signal, signalArg, and null terminator
{
// Add the signal number to the command line
signalArg = PROCFormatInt(signal);
if (signalArg != nullptr)
if (signalArg != nullptr && argc + 3 < MAX_ARGV_ENTRIES) // Need room for --signal, signalArg, and null terminator
{
argv.push_back("--signal");
argv.push_back(signalArg);
argv[argc++] = "--signal";
argv[argc++] = signalArg;
}

// Add the current thread id to the command line. This function is always called on the crashing thread.
crashThreadArg = PROCFormatInt(THREADSilentGetCurrentThreadId());
if (crashThreadArg != nullptr)
if (crashThreadArg != nullptr && argc + 3 < MAX_ARGV_ENTRIES) // Need room for --crashthread, crashThreadArg, and null terminator
{
argv.push_back("--crashthread");
argv.push_back(crashThreadArg);
argv[argc++] = "--crashthread";
argv[argc++] = crashThreadArg;
}

if (siginfo != nullptr)
{
signalCodeArg = PROCFormatInt(siginfo->si_code);
if (signalCodeArg != nullptr)
if (signalCodeArg != nullptr && argc + 3 < MAX_ARGV_ENTRIES) // Need room for --code, signalCodeArg, and null terminator
{
argv.push_back("--code");
argv.push_back(signalCodeArg);
argv[argc++] = "--code";
argv[argc++] = signalCodeArg;
}
signalErrnoArg = PROCFormatInt(siginfo->si_errno);
if (signalErrnoArg != nullptr)
if (signalErrnoArg != nullptr && argc + 3 < MAX_ARGV_ENTRIES) // Need room for --errno, signalErrnoArg, and null terminator
{
argv.push_back("--errno");
argv.push_back(signalErrnoArg);
argv[argc++] = "--errno";
argv[argc++] = signalErrnoArg;
}
signalAddressArg = PROCFormatInt64((ULONG64)siginfo->si_addr);
if (signalAddressArg != nullptr)
if (signalAddressArg != nullptr && argc + 3 < MAX_ARGV_ENTRIES) // Need room for --address, signalAddressArg, and null terminator
{
argv.push_back("--address");
argv.push_back(signalAddressArg);
argv[argc++] = "--address";
argv[argc++] = signalAddressArg;
}
}

argv.push_back(nullptr);
if (argc < MAX_ARGV_ENTRIES)
{
argv[argc++] = nullptr;
}
}
else
{
if (argc < MAX_ARGV_ENTRIES)
{
argv[argc] = nullptr;
}
}

PROCCreateCrashDump(argv, nullptr, 0, serialize);
Expand Down
Loading