Skip to content
This repository has been archived by the owner on Jun 18, 2021. It is now read-only.

Commit

Permalink
This patch adds the command line used to start the process to noderep…
Browse files Browse the repository at this point in the history
…ort on

Linux, Mac and AIX.
On Linux it reads /proc/self/cmdline.
On Mac is uses _NSGetArgv and _NSGetArgc.
On AIX it reads /proc/PID/psinfo.

The command line is read and stored at startup so files aren't opened
when a crash is occuring.
  • Loading branch information
hhellyer committed Jan 4, 2017
1 parent 8605e4c commit d5673b8
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ void Initialize(v8::Local<v8::Object> exports) {

SetLoadTime();
SetVersionString(isolate);
SetCommandLine();

const char* verbose_switch = secure_getenv("NODEREPORT_VERBOSE");
if (verbose_switch != nullptr) {
Expand Down
86 changes: 84 additions & 2 deletions src/node_report.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <dlfcn.h>
#ifndef _AIX
#include <execinfo.h>
#else
#include <sys/procfs.h>
#endif
#include <sys/utsname.h>
#endif
Expand All @@ -41,6 +43,11 @@
#define UNKNOWN_NODEVERSION_STRING "Unable to determine Node.js version\n"
#endif

#ifdef __APPLE__
// Include _NSGetArgv and _NSGetArgc for command line arguments.
#include <crt_externs.h>
#endif

#ifndef _WIN32
extern char** environ;
#endif
Expand All @@ -58,6 +65,7 @@ using v8::String;
using v8::V8;

// Internal/static function declarations
static void PrintCommandLine(FILE* fp);
static void PrintVersionInformation(FILE* fp, Isolate* isolate);
static void PrintJavaScriptStack(FILE* fp, Isolate* isolate, DumpEvent event, const char* location);
static void PrintStackFromStackTrace(FILE* fp, Isolate* isolate, DumpEvent event);
Expand All @@ -77,6 +85,7 @@ static bool report_active = false; // recursion protection
static char report_filename[NR_MAXNAME + 1] = "";
static char report_directory[NR_MAXPATH + 1] = ""; // defaults to current working directory
static std::string version_string = UNKNOWN_NODEVERSION_STRING;
static std::string commandline_string = "";
#ifdef _WIN32
static SYSTEMTIME loadtime_tm_struct; // module load time
#else // UNIX, OSX
Expand Down Expand Up @@ -299,6 +308,65 @@ void SetLoadTime() {
localtime_r(&time_val.tv_sec, &loadtime_tm_struct);
#endif
}

/*******************************************************************************
* Function to save the process command line
*******************************************************************************/
void SetCommandLine() {
#ifdef __linux__
// Read the command line from /proc/self/cmdline
char buf[64];
FILE* cmdline_fd = fopen("/proc/self/cmdline", "r");
if (cmdline_fd == nullptr) {
return;
}
commandline_string = "";
int bytesread = fread(buf, 1, sizeof(buf), cmdline_fd);
while (bytesread > 0) {
for (int i = 0; i < bytesread; i++) {
// Arguments are null separated.
if (buf[i] == '\0') {
commandline_string += " ";
} else {
commandline_string += buf[i];
}
}
bytesread = fread(buf, 1, sizeof(buf), cmdline_fd);
}
fclose(cmdline_fd);
#elif __APPLE__
char **argv = *_NSGetArgv();
int argc = *_NSGetArgc();

commandline_string = "";
std::string seperator = "";
for (int i = 0; i < argc; i++) {
commandline_string += seperator + argv[i];
seperator = " ";
}
#elif _AIX
// Read the command line from /proc/self/cmdline
char procbuf[64];
snprintf(procbuf, sizeof(procbuf), "/proc/%d/psinfo", getpid());
FILE* psinfo_fd = fopen(procbuf, "r");
if (psinfo_fd == nullptr) {
return;
}
psinfo_t info;
int bytesread = fread(&info, 1, sizeof(psinfo_t), psinfo_fd);
fclose(psinfo_fd);
if (bytesread == sizeof(psinfo_t)) {
commandline_string = "";
std::string seperator = "";
char **argv = *((char ***) info.pr_argv);
for (uint32_t i = 0; i < info.pr_argc; i++) {
commandline_string += seperator + argv[i];
seperator = " ";
}
}
#endif // _AIX
}

/*******************************************************************************
* Main API function to write a NodeReport to file.
*
Expand All @@ -311,7 +379,7 @@ void SetLoadTime() {
******************************************************************************/
void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, const char* location, char* name) {
// Recursion check for NodeReport in progress, bail out
if (report_active) return;
if (report_active) return;
report_active = true;

// Obtain the current time and the pid (platform dependent)
Expand Down Expand Up @@ -414,6 +482,10 @@ void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, c
fprintf(fp, "Process ID: %d\n", pid);
fflush(fp);

// Print out the command line.
PrintCommandLine(fp);
fflush(fp);

// Print Node.js and OS version information
PrintVersionInformation(fp, isolate);
fflush(fp);
Expand Down Expand Up @@ -463,6 +535,16 @@ void TriggerNodeReport(Isolate* isolate, DumpEvent event, const char* message, c
report_active = false;
}

/*******************************************************************************
* Function to print process command line.
*
******************************************************************************/
static void PrintCommandLine(FILE* fp) {
if (commandline_string != "") {
fprintf(fp, "Command line arguments: %s\n", commandline_string.c_str());
}
}

/*******************************************************************************
* Function to print Node.js version, OS version and machine information
*
Expand Down Expand Up @@ -688,7 +770,7 @@ void PrintNativeStack(FILE* fp) {
SymInitialize(hProcess, nullptr, TRUE);

WORD numberOfFrames = CaptureStackBackTrace(2, 64, frames, nullptr);

// Walk the frames printing symbolic information if available
for (int i = 0; i < numberOfFrames; i++) {
DWORD64 dwOffset64 = 0;
Expand Down
1 change: 1 addition & 0 deletions src/node_report.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ unsigned int ProcessNodeReportVerboseSwitch(const char* args);

void SetLoadTime();
void SetVersionString(Isolate* isolate);
void SetCommandLine();

// Local implementation of secure_getenv()
inline const char* secure_getenv(const char* key) {
Expand Down

0 comments on commit d5673b8

Please sign in to comment.