Skip to content

Commit

Permalink
Merge pull request #14525 from keithc-ca/cmdline31
Browse files Browse the repository at this point in the history
(0.31.0) Capture command line in environment on AIX, Linux, Windows, Mac
  • Loading branch information
pshipton authored Feb 22, 2022
2 parents 7698672 + 0e5de61 commit ea2ab03
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2009, 2014 IBM Corp. and others
* Copyright (c) 2009, 2022 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -80,39 +80,41 @@ public int hashCode() {
}

/**
* This method tries to get environment variables by iterating through modules.
* It returns the one with environment var "IBM_JAVA_COMMAND_LINE"
* If there is no module with IBM_JAVA_COMMAND_LINE, then it returns the last one.
*
* @return Properties instance of environment variables.
* This method tries to get environment variables by iterating through modules.
* It returns the one with environment variable "OPENJ9_JAVA_COMMAND_LINE" or
* "IBM_JAVA_COMMAND_LINE". If no module has either, then it returns the last one.
*
* @return Properties instance of environment variables
* @throws DataUnavailableException
* @throws CorruptDataException
*/
public Properties getEnvironmentVariables() throws DataUnavailableException, CorruptDataException
{
if (null == environment) {
LinkedList<ISymbol> environSymbols = getEnvironmentSymbols();
ISymbol environ = null;

if (0 == environSymbols.size()) {
List<ISymbol> environSymbols = getEnvironmentSymbols();

if (environSymbols.isEmpty()) {
throw new DataUnavailableException("Couldn't find environment symbol");
}

/* There might be more than one module with environment variables. Use the one that has IBM_JAVA_COMMAND_LINE */
for (int i = 0; i < environSymbols.size(); i++ ) {
environ = environSymbols.get(i);

/*
* There might be more than one module with environment variables.
* Use the one that has OPENJ9_JAVA_COMMAND_LINE or IBM_JAVA_COMMAND_LINE.
*/
for (ISymbol environ : environSymbols) {
long environPointer = getPointerAt(environ.getAddress());
environment = EnvironmentUtils.readEnvironment(this,environPointer);
if (environment.containsKey("IBM_JAVA_COMMAND_LINE")) {
environment = EnvironmentUtils.readEnvironment(this, environPointer);
if (environment.containsKey("OPENJ9_JAVA_COMMAND_LINE")
|| environment.containsKey("IBM_JAVA_COMMAND_LINE")
) {
break;
}
}
}

return environment;
}


/**
* This method returns a list of symbols with the name "_environ"
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 1991, 2019 IBM Corp. and others
* Copyright (c) 1991, 2022 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -63,7 +63,8 @@
*/
public class J9DDRImageProcess implements ImageProcess {

private static final String JAVA_COMMAND_LINE_ENVIRONMENT_VARIABLE = "IBM_JAVA_COMMAND_LINE";
private static final String JAVA_COMMAND_LINE_ENVIRONMENT_VARIABLE = "OPENJ9_JAVA_COMMAND_LINE";
private static final String LEGACY_JAVA_COMMAND_LINE_ENVIRONMENT_VARIABLE = "IBM_JAVA_COMMAND_LINE";
private final IProcess process;
private boolean processDataSet = false;
private ProcessData j9rasProcessData;
Expand Down Expand Up @@ -149,10 +150,17 @@ public String getCommandLine() throws DataUnavailable, CorruptDataException {
try {
Properties environment = getEnvironment();
String javaCommandLine = environment.getProperty(JAVA_COMMAND_LINE_ENVIRONMENT_VARIABLE);


if (javaCommandLine != null) {
return javaCommandLine;
}

javaCommandLine = environment.getProperty(LEGACY_JAVA_COMMAND_LINE_ENVIRONMENT_VARIABLE);

if (javaCommandLine != null) {
return javaCommandLine;
}

return process.getCommandLine();
} catch (com.ibm.j9ddr.CorruptDataException e) {
throw new DTFJCorruptDataException(process,e);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*[INCLUDE-IF Sidecar18-SE]*/
/*******************************************************************************
* Copyright (c) 2004, 2020 IBM Corp. and others
* Copyright (c) 2004, 2022 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -1493,7 +1493,10 @@ private Object readProcess(DataEntry entry, Builder builder, Object addressSpace
Properties environment = getEnvironmentVariables(builder);
String alternateCommandLine = ""; //$NON-NLS-1$
if (null != environment) {
alternateCommandLine = environment.getProperty("IBM_JAVA_COMMAND_LINE", ""); //$NON-NLS-1$ //$NON-NLS-2$
alternateCommandLine = environment.getProperty("OPENJ9_JAVA_COMMAND_LINE", null); //$NON-NLS-1$
if (null == alternateCommandLine) {
alternateCommandLine = environment.getProperty("IBM_JAVA_COMMAND_LINE", ""); //$NON-NLS-1$ //$NON-NLS-2$
}
}

String commandLine = dumpCommandLine.length() >= alternateCommandLine.length() ? dumpCommandLine : alternateCommandLine;
Expand Down Expand Up @@ -1583,7 +1586,8 @@ private List<?> readModules(Builder builder, Object addressSpace, String executa
} else {
// Use override for the executable name. This supports the jextract -f <executable> option, for
// cases where the launcher path+name is truncated by the 80 character OS limit, AND it was a
// custom launcher, so the alternative IBM_JAVA_COMMAND_LINE property was not set.
// custom launcher, so the alternative property OPENJ9_JAVA_COMMAND_LINE (or IBM_JAVA_COMMAND_LINE)
// was not set.
file = _findFileInPath(builder, overrideExecutableName, classPath);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*[INCLUDE-IF Sidecar18-SE]*/
/*******************************************************************************
* Copyright (c) 2004, 2018 IBM Corp. and others
* Copyright (c) 2004, 2022 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -715,7 +715,10 @@ private void buildAddressSpace(Builder builder, int asid, boolean is64Bit) {
builder.setExecutableUnavailable("unable to extract executable information");
//System.out.println("Bad EDB "+edb);
}
String commandLine = environment.getProperty("IBM_JAVA_COMMAND_LINE", "");
String commandLine = environment.getProperty("OPENJ9_JAVA_COMMAND_LINE", null);
if (commandLine == null) {
commandLine = environment.getProperty("IBM_JAVA_COMMAND_LINE", "");
}
//Use the EDB address for the process id, if available, otherwise use the Address space id.
String pid = edb != null ? format(edb.address()) : format(asid);
if (null != _j9rasReader) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*[INCLUDE-IF Sidecar18-SE]*/
/*******************************************************************************
* Copyright (c) 2004, 2017 IBM Corp. and others
* Copyright (c) 2004, 2022 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -50,9 +50,9 @@ public class ImageProcess implements com.ibm.dtfj.image.ImageProcess
private long _faultingNativeID = 0; //the ID of the native thread which caused the GPF (if there was one)
private int _signalNumber = 0;
private Exception _runtimeCheckFailure;
private static final String JAVA_COMMAND_LINE_ENVIRONMENT_VARIABLE = "IBM_JAVA_COMMAND_LINE";

private static final String JAVA_COMMAND_LINE_ENVIRONMENT_VARIABLE = "OPENJ9_JAVA_COMMAND_LINE";
private static final String LEGACY_JAVA_COMMAND_LINE_ENVIRONMENT_VARIABLE = "IBM_JAVA_COMMAND_LINE";

public ImageProcess(String pid, String commandLine, Properties environment, ImageThread currentThread, Iterator threads, ImageModule executable, Iterator libraries, int pointerSize)
{
_id = pid;
Expand All @@ -77,10 +77,17 @@ public String getCommandLine() throws DataUnavailable, CorruptDataException
// all platforms we now try that first, with the core reader as a fallback.
Properties environment = getEnvironment();
String javaCommandLine = environment.getProperty(JAVA_COMMAND_LINE_ENVIRONMENT_VARIABLE);

if (javaCommandLine != null) {
return javaCommandLine;
}

javaCommandLine = environment.getProperty(LEGACY_JAVA_COMMAND_LINE_ENVIRONMENT_VARIABLE);

if (javaCommandLine != null) {
return javaCommandLine;
}

if (_commandLine == null) {
throw new DataUnavailable("Command line unavailable from core dump");
}
Expand Down
186 changes: 186 additions & 0 deletions runtime/j9vm/jvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,21 @@
#include "jitserver_error.h"
#endif /* J9VM_OPT_JITSERVER */

#if defined(AIXPPC)
#include <procinfo.h>
#include <sys/types.h>
#include <unistd.h>
#endif /* defined(AIXPPC) */

#if defined(OSX)
#include <sys/types.h>
#include <sys/sysctl.h>
#endif /* defined(OSX) */

#if defined(WIN32)
#include <processenv.h>
#include <stdlib.h>
#endif /* defined(WIN32) */

/* Must include this after j9vm_internal.h */
#include <string.h>
Expand Down Expand Up @@ -452,6 +467,176 @@ static const J9SignalMapping signalMap[] = {
{NULL, J9_SIG_ERR}
};

static void
captureCommandLine(void)
{
#if defined(WIN32)
#define ENV_VAR_NAME L"OPENJ9_JAVA_COMMAND_LINE"
#else /* defined(WIN32) */
#define ENV_VAR_NAME "OPENJ9_JAVA_COMMAND_LINE"
#endif /* defined(WIN32) */

#if defined(AIXPPC)
long int bufferSize = sysconf(_SC_ARG_MAX);

if (bufferSize > 0) {
char *buffer = malloc(bufferSize);

if (NULL != buffer) {
#if defined(J9VM_ENV_DATA64)
struct procsinfo64 info;
#else /* defined(J9VM_ENV_DATA64) */
struct procsinfo info;
#endif /* defined(J9VM_ENV_DATA64) */

memset(&info, '\0', sizeof(info));
info.pi_pid = getpid();

if (0 == getargs(&info, sizeof(info), buffer, bufferSize)) {
char *cursor = buffer;

/* replace the internal NULs with spaces */
for (;; ++cursor) {
if ('\0' == *cursor) {
if ('\0' == cursor[1]) {
/* the list ends with two NUL characters */
break;
}
*cursor = ' ';
}
}

/* it's not fatal if setenv() fails, so don't bother checking */
setenv(ENV_VAR_NAME, buffer, 1 /* overwrite */);
}

free(buffer);
}
}
#elif defined(LINUX) /* defined(AIXPPC) */
int fd = open("/proc/self/cmdline", O_RDONLY, 0);

if (fd >= 0) {
char *buffer = NULL;
size_t length = 0;
for (;;) {
char small_buffer[512];
ssize_t count = read(fd, small_buffer, sizeof(small_buffer));
if (count <= 0) {
break;
}
length += (size_t)count;
}
if (length < 2) {
goto done;
}
/* final NUL is already included in length */
buffer = malloc(length);
if (NULL == buffer) {
goto done;
}
if ((off_t)-1 == lseek(fd, 0, SEEK_SET)) {
goto done;
}
if (read(fd, buffer, length) != length) {
goto done;
}
/* replace the internal NULs with spaces */
for (length -= 2;; length -= 1) {
if (0 == length) {
break;
}
if ('\0' == buffer[length]) {
buffer[length] = ' ';
}
}
/* it's not fatal if setenv() fails, so don't bother checking */
setenv(ENV_VAR_NAME, buffer, 1 /* overwrite */);
done:
if (NULL != buffer) {
free(buffer);
}
close(fd);
}
#elif defined(OSX) /* defined(AIXPPC) */
int argmax = 0;
size_t length = 0;
int mib[3];

/* query the argument space limit */
mib[0] = CTL_KERN;
mib[1] = KERN_ARGMAX;
length = sizeof(argmax);
if (0 == sysctl(mib, 2, &argmax, &length, NULL, 0)) {
char *buffer = malloc(argmax);

if (NULL != buffer) {
int argc = 0;
int pid = getpid();

/* query the argument count */
mib[0] = CTL_KERN;
mib[1] = KERN_PROCARGS2;
mib[2] = pid;
length = argmax;
if ((argmax >= sizeof(argc)) && (0 == sysctl(mib, 3, buffer, &length, NULL, 0))) {
memcpy(&argc, buffer, sizeof(argc));

/* retrieve the arguments */
mib[0] = CTL_KERN;
mib[1] = KERN_PROCARGS;
mib[2] = pid;
length = argmax;
if (0 == sysctl(mib, 3, buffer, &length, NULL, 0)) {
char *cursor = buffer;
char *start = NULL;
char *limit = buffer + length;

for (; (cursor < limit) && ('\0' != *cursor); ++cursor) {
/* skip past the program path */
}

for (; (cursor < limit) && ('\0' == *cursor); ++cursor) {
/* skip past the padding after the program path */
}

/*
* remember the start of the first argument (this is the beginning
* of argv[0] which is often the same as the path we skipped above)
*/
start = cursor;

/* replace the internal NULs with spaces */
for (; cursor < limit; ++cursor) {
if ('\0' == *cursor) {
argc -= 1;
if (0 == argc) {
break;
}
*cursor = ' ';
}
}

/* it's not fatal if setenv() fails, so don't bother checking */
setenv(ENV_VAR_NAME, start, 1 /* overwrite */);
}
}

free(buffer);
}
}
#elif defined(WIN32) /* defined(AIXPPC) */
const wchar_t *commandLine = GetCommandLineW();

if (NULL != commandLine) {
/* it's not fatal if _wputenv_s() fails, so don't bother checking */
_wputenv_s(ENV_VAR_NAME, commandLine);
}
#endif /* defined(AIXPPC) */

#undef ENV_VAR_NAME
}

static void freeGlobals(void)
{
free(newPath);
Expand Down Expand Up @@ -1657,6 +1842,7 @@ JNI_CreateJavaVM_impl(JavaVM **pvm, void **penv, void *vm_args, BOOLEAN isJITSer
return JNI_ERR;
}
#endif /* defined(J9ZTPF) */
captureCommandLine();
/*
* Linux uses LD_LIBRARY_PATH
* z/OS uses LIBPATH
Expand Down
Loading

0 comments on commit ea2ab03

Please sign in to comment.