Commit e8832eb9 authored by Duncan Coutts's avatar Duncan Coutts

Emit various bits of OS process info into the eventlog

The process ID, parent process ID, rts name and version
The program arguments and environment.
parent 43c7d555
......@@ -112,6 +112,7 @@
#define EVENT_GC_END 10 /* () */
#define EVENT_REQUEST_SEQ_GC 11 /* () */
#define EVENT_REQUEST_PAR_GC 12 /* () */
/* 13, 14 deprecated */
#define EVENT_CREATE_SPARK_THREAD 15 /* (spark_thread) */
#define EVENT_LOG_MSG 16 /* (message ...) */
#define EVENT_STARTUP 17 /* (num_capabilities) */
......@@ -120,12 +121,40 @@
#define EVENT_GC_IDLE 20 /* () */
#define EVENT_GC_WORK 21 /* () */
#define EVENT_GC_DONE 22 /* () */
/* 23, 24 used by eden */
#define EVENT_CAPSET_CREATE 25 /* (capset, capset_type) */
#define EVENT_CAPSET_DELETE 26 /* (capset) */
#define EVENT_CAPSET_ASSIGN_CAP 27 /* (capset, cap) */
#define EVENT_CAPSET_REMOVE_CAP 28 /* (capset, cap) */
/* the RTS identifier is in the form of "GHC-version rts_way" */
#define EVENT_RTS_IDENTIFIER 29 /* (capset, name_version_string) */
/* the vectors in these events are null separated strings */
#define EVENT_PROGRAM_ARGS 30 /* (capset, commandline_vector) */
#define EVENT_PROGRAM_ENV 31 /* (capset, environment_vector) */
#define EVENT_OSPROCESS_PID 32 /* (capset, pid) */
#define EVENT_OSPROCESS_PPID 33 /* (capset, parent_pid) */
#define NUM_EVENT_TAGS 23
/* Range 34 - 59 is available for new events */
/* Range 60 - 80 is used by eden for parallel tracing
* see http://www.mathematik.uni-marburg.de/~eden/
*/
/*
* The highest event code +1 that ghc itself emits. Note that some event
* ranges higher than this are reserved but not currently emitted by ghc.
* This must match the size of the EventDesc[] array in EventLog.c
*/
#define NUM_EVENT_TAGS 34
#if 0 /* DEPRECATED EVENTS: */
/* ghc changed how it handles sparks so these are no longer applicable */
#define EVENT_CREATE_SPARK 13 /* (cap, thread) */
#define EVENT_SPARK_TO_THREAD 14 /* (cap, thread, spark_thread) */
/* these are used by eden but are replaced by new alternatives for ghc */
#define EVENT_VERSION 23 /* (version_string) */
#define EVENT_PROGRAM_INVOCATION 24 /* (commandline_string) */
#endif
/*
......@@ -152,6 +181,13 @@
*/
#define THREAD_SUSPENDED_FOREIGN_CALL 6
/*
* Capset type values for EVENT_CAPSET_CREATE
*/
#define CAPSET_TYPE_CUSTOM 1 /* reserved for end-user applications */
#define CAPSET_TYPE_OSPROCESS 2 /* caps belong to the same OS process */
#define CAPSET_TYPE_CLOCKDOMAIN 3 /* caps share a local clock/time */
#ifndef EVENTLOG_CONSTANTS_ONLY
typedef StgWord16 EventTypeNum;
......@@ -160,6 +196,8 @@ typedef StgWord32 EventThreadID;
typedef StgWord16 EventCapNo;
typedef StgWord16 EventPayloadSize; /* variable-size events */
typedef StgWord16 EventThreadStatus; /* status for EVENT_STOP_THREAD */
typedef StgWord32 EventCapsetID;
typedef StgWord16 EventCapsetType; /* types for EVENT_CAPSET_CREATE */
#endif
......
/* -----------------------------------------------------------------------------
*
* (c) The GHC Team 2011
*
* OS-independent interface to the process environment variables
*
* ---------------------------------------------------------------------------*/
#ifndef GETENV_H
#define GETENV_H
#include "BeginPrivate.h"
/* Get the process environment vector (same style interface as argc/argv)
*/
void getProgEnvv (int *out_envc, char **out_envv[]);
void freeProgEnvv (int envc, char *envv[]);
/* calls to getProgEnvv must have a corresponding freeProgEnvv */
#include "EndPrivate.h"
#endif /* GETENV_H */
......@@ -153,6 +153,9 @@ hs_init(int *argc, char **argv[])
*/
initScheduler();
/* Trace some basic information about the process */
traceOSProcessInfo();
/* initialize the storage manager */
initStorage();
......
......@@ -15,11 +15,16 @@
#ifdef TRACING
#include "GetTime.h"
#include "GetEnv.h"
#include "Stats.h"
#include "eventlog/EventLog.h"
#include "Threads.h"
#include "Printer.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef DEBUG
// debugging flags, set with +RTS -D<something>
int DEBUG_sched;
......@@ -284,6 +289,50 @@ void traceCapsetModify_ (EventTypeNum tag,
}
}
void traceOSProcessInfo_(void) {
if (eventlog_enabled) {
postCapsetModifyEvent(EVENT_OSPROCESS_PID,
CAPSET_OSPROCESS_DEFAULT,
getpid());
#if !defined(cygwin32_HOST_OS) && !defined (mingw32_HOST_OS)
/* Windows has no strong concept of process heirarchy, so no getppid().
* In any case, this trace event is mainly useful for tracing programs
* that use 'forkProcess' which Windows doesn't support anyway.
*/
postCapsetModifyEvent(EVENT_OSPROCESS_PPID,
CAPSET_OSPROCESS_DEFAULT,
getppid());
#endif
{
char buf[256];
snprintf(buf, sizeof(buf), "GHC-%s %s", ProjectVersion, RtsWay);
postCapsetStrEvent(EVENT_RTS_IDENTIFIER,
CAPSET_OSPROCESS_DEFAULT,
buf);
}
{
int argc = 0; char **argv;
getFullProgArgv(&argc, &argv);
if (argc != 0) {
postCapsetVecEvent(EVENT_PROGRAM_ARGS,
CAPSET_OSPROCESS_DEFAULT,
argc, argv);
}
}
{
int envc = 0; char **envv;
getProgEnvv(&envc, &envv);
if (envc != 0) {
postCapsetVecEvent(EVENT_PROGRAM_ENV,
CAPSET_OSPROCESS_DEFAULT,
envc, envv);
}
freeProgEnvv(envc, envv);
}
}
}
void traceEvent_ (Capability *cap, EventTypeNum tag)
{
#ifdef DEBUG
......
......@@ -182,6 +182,8 @@ void traceCapsetModify_ (EventTypeNum tag,
CapsetID capset,
StgWord32 other);
void traceOSProcessInfo_ (void);
#else /* !TRACING */
#define traceSchedEvent(cap, tag, tso, other) /* nothing */
......@@ -194,6 +196,7 @@ void traceCapsetModify_ (EventTypeNum tag,
#define traceThreadStatus(class, tso) /* nothing */
#define traceEventStartup_(n_caps) /* nothing */
#define traceCapsetModify_(tag, capset, other) /* nothing */
#define traceOSProcessInfo_() /* nothing */
#endif /* TRACING */
......@@ -469,6 +472,13 @@ INLINE_HEADER void traceCapsetRemoveCap(CapsetID capset STG_UNUSED,
dtraceCapsetRemoveCap(capset, capno);
}
INLINE_HEADER void traceOSProcessInfo(void)
{
traceOSProcessInfo_();
/* Note: no DTrace equivalent because all this OS process info
* is available to DTrace directly */
}
#include "EndPrivate.h"
#endif /* TRACE_H */
......@@ -79,7 +79,12 @@ char *EventDesc[] = {
[EVENT_CAPSET_CREATE] = "Create capability set",
[EVENT_CAPSET_DELETE] = "Delete capability set",
[EVENT_CAPSET_ASSIGN_CAP] = "Add capability to capability set",
[EVENT_CAPSET_REMOVE_CAP] = "Remove capability from capability set"
[EVENT_CAPSET_REMOVE_CAP] = "Remove capability from capability set",
[EVENT_RTS_IDENTIFIER] = "RTS name and version",
[EVENT_PROGRAM_ARGS] = "Program arguments",
[EVENT_PROGRAM_ENV] = "Program environment variables",
[EVENT_OSPROCESS_PID] = "Process ID",
[EVENT_OSPROCESS_PPID] = "Parent process ID"
};
// Event type.
......@@ -284,6 +289,12 @@ initEventLogging(void)
sizeof(EventCapsetID) + sizeof(EventCapNo);
break;
case EVENT_OSPROCESS_PID: // (cap, pid)
case EVENT_OSPROCESS_PPID:
eventTypes[t].size =
sizeof(EventCapsetID) + sizeof(StgWord32);
break;
case EVENT_SHUTDOWN: // (cap)
case EVENT_REQUEST_SEQ_GC: // (cap)
case EVENT_REQUEST_PAR_GC: // (cap)
......@@ -297,6 +308,9 @@ initEventLogging(void)
case EVENT_LOG_MSG: // (msg)
case EVENT_USER_MSG: // (msg)
case EVENT_RTS_IDENTIFIER: // (capset, str)
case EVENT_PROGRAM_ARGS: // (capset, strvec)
case EVENT_PROGRAM_ENV: // (capset, strvec)
eventTypes[t].size = 0xffff;
break;
......@@ -496,6 +510,12 @@ void postCapsetModifyEvent (EventTypeNum tag,
postCapNo(&eventBuf, other /* capno */);
break;
}
case EVENT_OSPROCESS_PID: // (capset, pid)
case EVENT_OSPROCESS_PPID: // (capset, parent_pid)
{
postWord32(&eventBuf, other);
break;
}
default:
barf("postCapsetModifyEvent: unknown event tag %d", tag);
}
......@@ -503,6 +523,70 @@ void postCapsetModifyEvent (EventTypeNum tag,
RELEASE_LOCK(&eventBufMutex);
}
void postCapsetStrEvent (EventTypeNum tag,
EventCapsetID capset,
char *msg)
{
int strsize = strlen(msg);
int size = strsize + sizeof(EventCapsetID)
ACQUIRE_LOCK(&eventBufMutex);
if (!hasRoomForVariableEvent(&eventBuf, size)){
printAndClearEventBuf(&eventBuf);
if (!hasRoomForVariableEvent(&eventBuf, size)){
// Event size exceeds buffer size, bail out:
RELEASE_LOCK(&eventBufMutex);
return;
}
}
postEventHeader(&eventBuf, tag);
postPayloadSize(&eventBuf, size);
postCapsetID(&eventBuf, capset);
postBuf(&eventBuf, (StgWord8*) msg, strsize);
RELEASE_LOCK(&eventBufMutex);
}
void postCapsetVecEvent (EventTypeNum tag,
EventCapsetID capset,
int argc,
char *argv[])
{
int i, size = sizeof(EventCapsetID);
for (i = 0; i < argc; i++) {
// 1 + strlen to account for the trailing \0, used as separator
size += 1 + strlen(argv[i]);
}
ACQUIRE_LOCK(&eventBufMutex);
if (!hasRoomForVariableEvent(&eventBuf, size)){
printAndClearEventBuf(&eventBuf);
if(!hasRoomForVariableEvent(&eventBuf, size)){
// Event size exceeds buffer size, bail out:
RELEASE_LOCK(&eventBufMutex);
return;
}
}
postEventHeader(&eventBuf, tag);
postPayloadSize(&eventBuf, size);
postCapsetID(&eventBuf, capset);
for( i = 0; i < argc; i++ ) {
// again, 1 + to account for \0
postBuf(&eventBuf, (StgWord8*) argv[i], 1 + strlen(argv[i]));
}
RELEASE_LOCK(&eventBufMutex);
}
void
postEvent (Capability *cap, EventTypeNum tag)
{
......
......@@ -54,6 +54,21 @@ void postCapsetModifyEvent (EventTypeNum tag,
EventCapsetID capset,
StgWord32 other);
/*
* Post a capability set event with a string payload
*/
void postCapsetStrEvent (EventTypeNum tag,
EventCapsetID capset,
char *msg);
/*
* Post a capability set event with several strings payload
*/
void postCapsetVecEvent (EventTypeNum tag,
EventCapsetID capset,
int argc,
char *msg[]);
#else /* !TRACING */
INLINE_HEADER void postSchedEvent (Capability *cap STG_UNUSED,
......
......@@ -295,6 +295,7 @@ rts/RtsMain_HC_OPTS += -optc-O0
rts/RtsMessages_CC_OPTS += -DProjectVersion=\"$(ProjectVersion)\"
rts/RtsUtils_CC_OPTS += -DProjectVersion=\"$(ProjectVersion)\"
rts/Trace_CC_OPTS += -DProjectVersion=\"$(ProjectVersion)\"
#
rts/RtsUtils_CC_OPTS += -DHostPlatform=\"$(HOSTPLATFORM)\"
rts/RtsUtils_CC_OPTS += -DHostArch=\"$(HostArch_CPP)\"
......
/* -----------------------------------------------------------------------------
*
* (c) The GHC Team 2011
*
* Access to the process environment variables
*
* ---------------------------------------------------------------------------*/
#include "Rts.h"
#include "GetEnv.h"
#if defined(darwin_HOST_OS)
/* While the "extern char** environ" var does exist on OSX, it is not
* available to shared libs. See ghc ticket #2458 and
* http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man7/environ.7.html
*/
#include <crt_externs.h>
static char** get_environ(void) { return *(_NSGetEnviron()); }
#else
/* On proper unix systems the environ is just a global var.
*/
extern char** environ;
static char** get_environ(void) { return environ; }
#endif
void getProgEnvv(int *out_envc, char **out_envv[]) {
int envc;
char **environ = get_environ();
for (envc = 0; environ[envc] != NULL; envc++) {};
*out_envc = envc;
*out_envv = environ;
}
void freeProgEnvv(int envc STG_UNUSED, char *envv[] STG_UNUSED) {
/* nothing */
}
/* -----------------------------------------------------------------------------
*
* (c) The GHC Team 2011
*
* Access to the process environment variables
*
* ---------------------------------------------------------------------------*/
#include "Rts.h"
#include "GetEnv.h"
#include <windows.h>
/* Windows does it differently, though arguably the most sanely.
* GetEnvironmentStrings() returns a pointer to a block of
* environment vars with a double null terminator:
* Var1=Value1\0
* Var2=Value2\0
* ...
* VarN=ValueN\0\0
* But because everyone else (ie POSIX) uses a vector of strings, we convert
* to that format. Fortunately this is just a matter of making an array of
* offsets into the environment block.
*
* Note that we have to call FreeEnvironmentStrings() at the end.
*
*/
void getProgEnvv(int *out_envc, char **out_envv[]) {
int envc, i;
char *env;
char *envp;
char **envv;
/* For now, use the 'A'nsi not 'W'ide variant.
Note: corresponding Free below must use the same 'A'/'W' variant. */
env = GetEnvironmentStringsA();
envc = 0;
for (envp = env; *envp != 0; envp += strlen(envp) + 1) {
envc++;
}
envv = stgMallocBytes(sizeof(char*) * (envc+1));
i = 0;
for (envp = env; *envp != NULL; envp += strlen(envp) + 1) {
envv[i] = envp;
i++;
}
/* stash whole env in last+1 entry */
envv[envc] = env;
*out_envc = envc;
*out_envv = envv;
}
void freeProgEnvv(int envc, char *envv[]) {
/* we stashed the win32 env block in the last+1 entry */
FreeEnvironmentStringsA(envv[envc]);
stgFree(envv);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment