8274856: Failing jpackage tests with fastdebug/release build

Reviewed-by: almatvee, herrick
This commit is contained in:
Alexey Semenyuk 2021-11-15 17:57:58 +00:00
parent 9046077fe6
commit fe45835f7c
8 changed files with 259 additions and 47 deletions

View File

@ -29,7 +29,9 @@
#include <dlfcn.h>
#include <errno.h>
#include <linux/limits.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stddef.h>
#include <libgen.h>
#include "JvmLauncher.h"
#include "LinuxPackage.h"
@ -43,7 +45,7 @@ static int appArgc;
static char **appArgv;
static JvmlLauncherData* initJvmlLauncherData(void) {
static JvmlLauncherData* initJvmlLauncherData(int* size) {
char* launcherLibPath = 0;
void* jvmLauncherLibHandle = 0;
JvmlLauncherAPI_GetAPIFunc getApi = 0;
@ -86,7 +88,7 @@ static JvmlLauncherData* initJvmlLauncherData(void) {
goto cleanup;
}
result = jvmLauncherCreateJvmlLauncherData(api, jvmLauncherHandle);
result = jvmLauncherCreateJvmlLauncherData(api, jvmLauncherHandle, size);
/* Handle released in jvmLauncherCreateJvmlLauncherData() */
jvmLauncherHandle = 0;
@ -131,18 +133,129 @@ cleanup:
}
static void closePipeEnd(int* pipefd, int idx) {
if (pipefd[idx] >= 0) {
close(pipefd[idx]);
pipefd[idx] = -1;
}
}
static void initJvmlLauncherDataPointers(void* baseAddress,
JvmlLauncherData* jvmLauncherData) {
ptrdiff_t offset = (char*)jvmLauncherData - (char*)baseAddress;
int i;
jvmLauncherData->jliLibPath += offset;
jvmLauncherData->jliLaunchArgv =
(char**)((char*)jvmLauncherData->jliLaunchArgv + offset);
jvmLauncherData->envVarNames =
(char**)((char*)jvmLauncherData->envVarNames + offset);
jvmLauncherData->envVarValues =
(char**)((char*)jvmLauncherData->envVarValues + offset);
for (i = 0; i != jvmLauncherData->jliLaunchArgc; i++) {
jvmLauncherData->jliLaunchArgv[i] += offset;
}
for (i = 0; i != jvmLauncherData->envVarCount; i++) {
jvmLauncherData->envVarNames[i] += offset;
jvmLauncherData->envVarValues[i] += offset;
}
}
int main(int argc, char *argv[]) {
int pipefd[2];
pid_t cpid;
int exitCode = STATUS_FAILURE;
JvmlLauncherData* jvmLauncherData;
JvmlLauncherData* jvmLauncherData = 0;
int jvmLauncherDataBufferSize = 0;
appArgc = argc;
appArgv = argv;
jvmLauncherData = initJvmlLauncherData();
if (jvmLauncherData) {
exitCode = launchJvm(jvmLauncherData);
free(jvmLauncherData);
if (pipe(pipefd) == -1) {
JP_LOG_ERRNO;
return exitCode;
}
cpid = fork();
if (cpid == -1) {
JP_LOG_ERRNO;
} else if (cpid == 0) /* Child process */ {
/* Close unused read end */
closePipeEnd(pipefd, 0);
jvmLauncherData = initJvmlLauncherData(&jvmLauncherDataBufferSize);
if (jvmLauncherData) {
/* Buffer size */
if (write(pipefd[1], &jvmLauncherDataBufferSize,
sizeof(jvmLauncherDataBufferSize)) == -1) {
JP_LOG_ERRNO;
goto cleanup;
}
if (jvmLauncherDataBufferSize) {
/* Buffer address */
if (write(pipefd[1], &jvmLauncherData,
sizeof(jvmLauncherData)) == -1) {
JP_LOG_ERRNO;
goto cleanup;
}
/* Buffer data */
if (write(pipefd[1], jvmLauncherData,
jvmLauncherDataBufferSize) == -1) {
JP_LOG_ERRNO;
goto cleanup;
}
}
}
exitCode = 0;
} else if (cpid > 0) {
void* baseAddress = 0;
/* Close unused write end */
closePipeEnd(pipefd, 1);
if (read(pipefd[0], &jvmLauncherDataBufferSize,
sizeof(jvmLauncherDataBufferSize)) == -1) {
JP_LOG_ERRNO;
goto cleanup;
}
if (jvmLauncherDataBufferSize == 0) {
JP_LOG_ERRNO;
goto cleanup;
}
if (read(pipefd[0], &baseAddress, sizeof(baseAddress)) == -1) {
JP_LOG_ERRNO;
goto cleanup;
}
jvmLauncherData = malloc(jvmLauncherDataBufferSize);
if (!jvmLauncherData) {
JP_LOG_ERRNO;
goto cleanup;
}
if (read(pipefd[0], jvmLauncherData,
jvmLauncherDataBufferSize) == -1) {
JP_LOG_ERRNO;
goto cleanup;
}
closePipeEnd(pipefd, 0);
wait(NULL); /* Wait child process to terminate */
initJvmlLauncherDataPointers(baseAddress, jvmLauncherData);
exitCode = launchJvm(jvmLauncherData);
}
cleanup:
closePipeEnd(pipefd, 0);
closePipeEnd(pipefd, 1);
free(jvmLauncherData);
return exitCode;
}

View File

@ -113,17 +113,9 @@ void launchApp() {
launchInfo = (tstrings::any() << thisHash).str();
}
JP_TRY;
if (0 != setenv(_JPACKAGE_LAUNCHER.c_str(), launchInfo.c_str(), 1)) {
JP_THROW(tstrings::any() << "setenv(" << _JPACKAGE_LAUNCHER
<< ", " << launchInfo << ") failed. Error: " << lastCRTError());
} else {
LOG_TRACE(tstrings::any() << "Set "
<< _JPACKAGE_LAUNCHER << "=[" << launchInfo << "]");
}
JP_CATCH_ALL;
jvmLauncher = appLauncher.createJvmLauncher();
jvmLauncher->addEnvVariable(_JPACKAGE_LAUNCHER, launchInfo);
}
} // namespace

View File

@ -130,15 +130,15 @@ Jvm* AppLauncher::createJvmLauncher() const {
PropertyName::arguments, args);
}
std::unique_ptr<Jvm> jvm(new Jvm());
if (!libEnvVariableContainsAppDir()) {
SysInfo::setEnvVariable(libEnvVarName, SysInfo::getEnvVariable(
(*jvm).addEnvVariable(libEnvVarName, SysInfo::getEnvVariable(
std::nothrow, libEnvVarName)
+ FileUtils::pathSeparator
+ appDirPath);
}
std::unique_ptr<Jvm> jvm(new Jvm());
(*jvm)
.setPath(findJvmLib(cfgFile, defaultRuntimePath, jvmLibNames))
.addArgument(launcherPath);

View File

@ -201,7 +201,7 @@ void Jvm::launch() {
JvmlLauncherAPI* api = jvmLauncherGetAPI();
AutoJvmlLauncherData jld(jvmLauncherCreateJvmlLauncherData(api,
jlh.release()));
jlh.release(), 0));
LOG_TRACE(tstrings::any() << "JVM library: \"" << jvmPath << "\"");
@ -215,11 +215,20 @@ void Jvm::launch() {
}
void Jvm::setEnvVariables() {
for (size_t i = 0; i != envVarNames.size(); i++) {
SysInfo::setEnvVariable(envVarNames.at(i), envVarValues.at(i));
}
}
namespace {
struct JliLaunchData {
std::string jliLibPath;
std::vector<std::string> args;
tstring_array envVarNames;
tstring_array envVarValues;
int initJvmlLauncherData(JvmlLauncherData* ptr, int bufferSize) const {
int minimalBufferSize = initJvmlLauncherData(0);
@ -230,6 +239,29 @@ struct JliLaunchData {
}
private:
template <class T>
static char* copyStrings(const std::vector<T>& src,
JvmlLauncherData* ptr, const size_t offset, char* curPtr) {
char** strArray = 0;
if (ptr) {
strArray = *reinterpret_cast<char***>(
reinterpret_cast<char*>(ptr) + offset);
}
for (size_t i = 0; i != src.size(); i++) {
const size_t count = (src[i].size() + 1 /* trailing zero */)
* sizeof(typename T::value_type);
if (ptr) {
std::memcpy(curPtr, src[i].c_str(), count);
strArray[i] = curPtr;
}
curPtr += count;
};
return curPtr;
}
int initJvmlLauncherData(JvmlLauncherData* ptr) const {
// Store path to JLI library just behind JvmlLauncherData header.
char* curPtr = reinterpret_cast<char*>(ptr + 1);
@ -243,26 +275,39 @@ private:
curPtr += count;
}
// Next write array of char* pointing to JLI lib arg strings.
// Write array of char* pointing to JLI lib arg strings.
if (ptr) {
ptr->jliLaunchArgv = reinterpret_cast<char**>(curPtr);
ptr->jliLaunchArgc = (int)args.size();
// Add terminal '0' arg.
ptr->jliLaunchArgv[ptr->jliLaunchArgc] = 0;
}
// Skip memory occupied by char* array.
// Skip memory occupied by JvmlLauncherData::jliLaunchArgv array.
curPtr += sizeof(char*) * (args.size() + 1 /* terminal '0' arg */);
// Store JLI lib arg strings.
curPtr = copyStrings(args, ptr,
offsetof(JvmlLauncherData, jliLaunchArgv), curPtr);
// Store array of strings.
for (size_t i = 0; i != args.size(); i++) {
const size_t count = (args[i].size() + 1 /* trailing zero */);
if (ptr) {
std::memcpy(curPtr, args[i].c_str(), count);
ptr->jliLaunchArgv[i] = curPtr;
}
curPtr += count;
};
// Write array of char* pointing to env variable name strings.
if (ptr) {
ptr->envVarNames = reinterpret_cast<TCHAR**>(curPtr);
ptr->envVarCount = (int)envVarNames.size();
}
// Skip memory occupied by JvmlLauncherData::envVarNames array.
curPtr += sizeof(TCHAR*) * envVarNames.size();
// Store env variable names.
curPtr = copyStrings(envVarNames, ptr,
offsetof(JvmlLauncherData, envVarNames), curPtr);
// Write array of char* pointing to env variable value strings.
if (ptr) {
ptr->envVarValues = reinterpret_cast<TCHAR**>(curPtr);
}
// Skip memory occupied by JvmlLauncherData::envVarValues array.
curPtr += sizeof(TCHAR*) * envVarValues.size();
// Store env variable values.
curPtr = copyStrings(envVarValues, ptr,
offsetof(JvmlLauncherData, envVarValues), curPtr);
const size_t bufferSize = curPtr - reinterpret_cast<char*>(ptr);
if (ptr) {
@ -276,6 +321,20 @@ private:
}
};
void copyStringArray(const tstring_array& src, std::vector<std::string>& dst) {
#ifdef TSTRINGS_WITH_WCHAR
{
tstring_array::const_iterator it = src.begin();
const tstring_array::const_iterator end = src.end();
for (; it != end; ++it) {
dst.push_back(tstrings::toACP(*it));
}
}
#else
dst = src;
#endif
}
} // namespace
JvmlLauncherHandle Jvm::exportLauncher() const {
@ -283,17 +342,9 @@ JvmlLauncherHandle Jvm::exportLauncher() const {
result->jliLibPath = tstrings::toUtf8(jvmPath);
#ifdef TSTRINGS_WITH_WCHAR
{
tstring_array::const_iterator it = args.begin();
const tstring_array::const_iterator end = args.end();
for (; it != end; ++it) {
result->args.push_back(tstrings::toACP(*it));
}
}
#else
result->args = args;
#endif
copyStringArray(args, result->args);
result->envVarNames = envVarNames;
result->envVarValues = envVarValues;
return result.release();
}

View File

@ -29,16 +29,27 @@
#include "jni.h" /* JNIEXPORT */
#ifdef _WIN32
#include <windows.h>
#include <tchar.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _WIN32
typedef char TCHAR;
#endif
typedef struct {
const char* jliLibPath;
int jliLaunchArgc;
int envVarCount;
char** jliLaunchArgv;
TCHAR** envVarNames;
TCHAR** envVarValues;
} JvmlLauncherData;
typedef void* JvmlLauncherHandle;
@ -71,7 +82,8 @@ static inline JvmlLauncherData* jvmLauncherInitJvmlLauncherData(JvmlLauncherAPI*
return (*api->initJvmlLauncherData)(h, ptr, bufferSize);
}
JvmlLauncherData* jvmLauncherCreateJvmlLauncherData(JvmlLauncherAPI* api, JvmlLauncherHandle h);
JvmlLauncherData* jvmLauncherCreateJvmlLauncherData(JvmlLauncherAPI* api,
JvmlLauncherHandle h, int* size);
int jvmLauncherStartJvm(JvmlLauncherData* jvmArgs, void* JLI_Launch);
void jvmLauncherLog(const char* format, ...);
@ -105,6 +117,12 @@ public:
return *this;
}
Jvm& addEnvVariable(const tstring& name, const tstring& value) {
envVarNames.push_back(name);
envVarValues.push_back(value);
return *this;
}
Jvm& setPath(const tstring& v) {
jvmPath = v;
return *this;
@ -118,11 +136,15 @@ public:
void launch();
void setEnvVariables();
JvmlLauncherHandle exportLauncher() const;
private:
tstring jvmPath;
tstring_array args;
tstring_array envVarNames;
tstring_array envVarValues;
};
#endif // #ifdef __cplusplus

View File

@ -26,6 +26,9 @@
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#ifdef LINUX
#include <unistd.h>
#endif
#include "JvmLauncher.h"
@ -44,7 +47,7 @@ typedef int (JNICALL *JLI_LaunchFuncType)(int argc, char ** argv,
JvmlLauncherData* jvmLauncherCreateJvmlLauncherData(
JvmlLauncherAPI* api, JvmlLauncherHandle h) {
JvmlLauncherAPI* api, JvmlLauncherHandle h, int* size) {
JvmlLauncherData* result = 0;
void* buf = 0;
int jvmLauncherDataBufferSize;
@ -69,6 +72,9 @@ JvmlLauncherData* jvmLauncherCreateJvmlLauncherData(
if (result) {
/* Don't free the buffer in clean up. */
buf = 0;
if (size) {
*size = jvmLauncherDataBufferSize;
}
}
cleanup:
@ -85,13 +91,33 @@ static void dumpJvmlLauncherData(const JvmlLauncherData* jvmArgs) {
for (i = 0; i < jvmArgs->jliLaunchArgc; ++i) {
JP_LOG_TRACE("jli arg[%d]: [%s]", i, jvmArgs->jliLaunchArgv[i]);
}
for (i = 0; i < jvmArgs->envVarCount; ++i) {
JP_LOG_TRACE("env var[%d]: %s=[%s]", i, jvmArgs->envVarNames[i],
jvmArgs->envVarValues[i]);
}
}
int jvmLauncherStartJvm(JvmlLauncherData* jvmArgs, void* JLI_Launch) {
int i;
int exitCode;
dumpJvmlLauncherData(jvmArgs);
for (i = 0; i < jvmArgs->envVarCount; ++i) {
#ifdef _WIN32
if (!SetEnvironmentVariable(jvmArgs->envVarNames[i],
jvmArgs->envVarValues[i])) {
JP_LOG_TRACE("SetEnvironmentVariable(%d) failed", i);
}
#else
if (setenv(jvmArgs->envVarNames[i],
jvmArgs->envVarValues[i], 1) != 0) {
JP_LOG_TRACE("setenv(%d) failed", i);
}
#endif
}
exitCode = (*((JLI_LaunchFuncType)JLI_Launch))(
jvmArgs->jliLaunchArgc, jvmArgs->jliLaunchArgv,
0, 0,
@ -121,6 +147,9 @@ void jvmLauncherLog(const char* format, ...) {
#if defined(__GNUC__) && __GNUC__ >= 5
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
#ifdef LINUX
fprintf(stderr, "[%d]: ", getpid());
#endif
vfprintf(stderr, format, args);
fprintf(stderr, "\n");

View File

@ -56,7 +56,10 @@ bool isEnvVariableSet(const tstring& name) {
}
void setEnvVariable(const tstring& name, const tstring& value) {
::setenv(name.c_str(), value.c_str(), 1);
if (::setenv(name.c_str(), value.c_str(), 1) != 0) {
JP_THROW(tstrings::any() << "setenv(" << name << ", " << value
<< ") failed. Error: " << lastCRTError());
}
}

View File

@ -152,6 +152,8 @@ void launchApp() {
std::unique_ptr<Jvm> jvm(appLauncher.createJvmLauncher());
if (restart) {
jvm->setEnvVariables();
jvm = std::unique_ptr<Jvm>();
STARTUPINFOW si;