Skip to content

Commit

Permalink
Add support for -Xrs on restore
Browse files Browse the repository at this point in the history
This PR adds support for -Xrs on restore. Given that its imposible to
support -Xrs in the same manner on restore that it is supported at startup
(because there may be frames on the stack with signal handlers already
installed that cannot be removed on restore) this change requires that
"onRestore" is appended to the option.

For example: -Xrs:sync -> -Xrs:syncOnRestore, -Xrs -> -Xrs:onRestore, ..

Signed-off-by: Tobi Ajila <atobia@ca.ibm.com>
  • Loading branch information
tajila committed Mar 16, 2023
1 parent 00d45a0 commit c29bc7e
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 5 deletions.
60 changes: 59 additions & 1 deletion runtime/vm/CRIUHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
*******************************************************************************/
#include <string.h>

#include "objhelp.h"
#include "j9.h"
#include "j9comp.h"
Expand Down Expand Up @@ -48,6 +50,7 @@ static IDATA findinstanceFieldOffsetHelper(J9VMThread *currentThread, J9Class *i
static void initializeCriuHooks(J9VMThread *currentThread);
static BOOLEAN juRandomReseed(J9VMThread *currentThread, void *userData, const char **nlsMsgFormat);
static BOOLEAN criuRestoreInitializeTrace(J9VMThread *currentThread, void *userData, const char **nlsMsgFormat);
static BOOLEAN criuRestoreInitializeXrs(J9VMThread *currentThread, void *userData, const char **nlsMsgFormat);
static jvmtiIterationControl objectIteratorCallback(J9JavaVM *vm, J9MM_IterateObjectDescriptor *objectDesc, void *userData);

BOOLEAN
Expand Down Expand Up @@ -232,7 +235,7 @@ juRandomReseed(J9VMThread *currentThread, void *userData, const char **nlsMsgFor
}

/**
* An internal JVM checkpoint hook is to initialize trace after restore.
* An internal JVM checkpoint hook to initialize trace after restore.
*
* @param[in] currentThread vmThread token
* @param[in] userData J9InternalHookRecord pointer
Expand Down Expand Up @@ -263,6 +266,60 @@ criuRestoreInitializeTrace(J9VMThread *currentThread, void *userData, const char
return result;
}

/**
* An internal JVM checkpoint hook to initialize -Xrs after restore. This only
* supports -Xrs options with "onRestore" appended to it.
*
* @param[in] currentThread vmThread token
* @param[in] userData J9InternalHookRecord pointer
* @param[in/out] nlsMsgFormat an NLS message
*
* @return Always returns TRUE
*/
static BOOLEAN
criuRestoreInitializeXrs(J9VMThread *currentThread, void *userData, const char **nlsMsgFormat)
{
J9JavaVM *vm = currentThread->javaVM;
J9VMInitArgs *args = vm->checkpointState.restoreArgsList;

if (NULL != args) {
IDATA argIndex = 0;
if ((argIndex = FIND_ARG_IN_ARGS(args, OPTIONAL_LIST_MATCH, VMOPT_XRS, NULL)) >= 0) {
bool argProcessed = false;
char* optionValue = NULL;
U_32 sigOptions = 0;

GET_OPTION_VALUE_ARGS(args, argIndex, ':', &optionValue);
if (NULL != optionValue) {
if (0 == strcmp(optionValue, "syncOnRestore")) {
vm->sigFlags |= J9_SIG_XRS_SYNC;
sigOptions |= J9PORT_SIG_OPTIONS_REDUCED_SIGNALS_SYNCHRONOUS;
argProcessed = true;
} else if (0 == strcmp(optionValue, "asyncOnRestore")) {
vm->sigFlags |= (J9_SIG_XRS_ASYNC | J9_SIG_NO_SIG_QUIT | J9_SIG_NO_SIG_USR2);
sigOptions |= J9PORT_SIG_OPTIONS_REDUCED_SIGNALS_ASYNCHRONOUS;
argProcessed = true;
} else if (0 == strcmp(optionValue, "onRestore")) {
vm->sigFlags |= (J9_SIG_XRS_SYNC | J9_SIG_XRS_ASYNC | J9_SIG_NO_SIG_QUIT | J9_SIG_NO_SIG_USR2);
sigOptions |= (J9PORT_SIG_OPTIONS_REDUCED_SIGNALS_SYNCHRONOUS | J9PORT_SIG_OPTIONS_REDUCED_SIGNALS_ASYNCHRONOUS);
argProcessed = true;
}
}

if (argProcessed) {
PORT_ACCESS_FROM_VMC(currentThread);
CONSUME_ARG(args, argIndex);
j9sig_set_options(sigOptions);
}
}
}

/* In cases of error (arg options are not supported) the entire args is not consumed.
* Return TRUE as checkpointJVMImpl will throw an exception if any arg is not consumed.
*/
return TRUE;
}

/**
* This cleans up the instanceObjects associated with each J9JavaVM->checkpointState.hookRecords,
* the hookRecords and classIterationRestoreHookRecords as well if checkpointState.isNonPortableRestoreMode is TRUE.
Expand Down Expand Up @@ -348,6 +405,7 @@ initializeCriuHooks(J9VMThread *currentThread)
addInternalJVMCheckpointHook(currentThread, TRUE, juRandomClass, FALSE, juRandomReseed);
}
addInternalJVMCheckpointHook(currentThread, TRUE, NULL, FALSE, criuRestoreInitializeTrace);
addInternalJVMCheckpointHook(currentThread, TRUE, NULL, FALSE, criuRestoreInitializeXrs);
}

done:
Expand Down
89 changes: 85 additions & 4 deletions test/functional/cmdLineTests/criu/criu_nonPortable.xml
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@
<output type="success" caseSensitive="yes" regex="no">Restore arg: -Dprop2=val2</output>
<output type="success" caseSensitive="yes" regex="no">Restore arg: -Dprop3=val3</output>
</test>
<test id="Properties test9">
<test id="Envvar test9">
<command>bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$" $MAINCLASS_ENVVAR_TEST$ EnvVarFileTest9 1</command>
<output type="success" caseSensitive="no" regex="no">Killed</output>
<output type="failure" caseSensitive="yes" regex="no">failed properties test</output>
Expand All @@ -510,7 +510,7 @@
<!-- In the past, the failure below was caused by an issue where CRIU can't be found on the PATH. -->
<output type="failure" caseSensitive="yes" regex="no">Could not dump the JVM processes, err=-70</output>
</test>
<test id="Properties test10">
<test id="Envvar test10">
<command>bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$" $MAINCLASS_ENVVAR_TEST$ EnvVarFileTest10 1</command>
<output type="success" caseSensitive="no" regex="no">Killed</output>
<output type="failure" caseSensitive="yes" regex="no">failed properties test</output>
Expand All @@ -525,7 +525,7 @@
<!-- In the past, the failure below was caused by an issue where CRIU can't be found on the PATH. -->
<output type="failure" caseSensitive="yes" regex="no">Could not dump the JVM processes, err=-70</output>
</test>
<test id="Properties test11">
<test id="Envvar test11">
<command>bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$" $MAINCLASS_ENVVAR_TEST$ EnvVarFileTest11 1</command>
<output type="success" caseSensitive="no" regex="no">Killed</output>
<output type="failure" caseSensitive="yes" regex="no">failed properties test</output>
Expand All @@ -540,7 +540,88 @@
<!-- In the past, the failure below was caused by an issue where CRIU can't be found on the PATH. -->
<output type="failure" caseSensitive="yes" regex="no">Could not dump the JVM processes, err=-70</output>
</test>

<test id="Envvar test12">
<command>bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$ -Xtrace:print=j9criu.16" $MAINCLASS_ENVVAR_TEST$ EnvVarFileTest12 1</command>
<output type="success" caseSensitive="no" regex="no">Killed</output>
<output type="failure" caseSensitive="yes" regex="no">failed properties test</output>
<output type="required" caseSensitive="yes" regex="no">Pre-checkpoint</output>
<output type="success" caseSensitive="yes" regex="no">Failed to load options from the options file</output>
<output type="failure" caseSensitive="yes" regex="no">CRIU is not enabled</output>
<output type="failure" caseSensitive="yes" regex="no">Operation not permitted</output>
<!-- If CRIU can't acquire the original thread IDs, this test will fail. Nothing can be done about this failure. -->
<output type="success" caseSensitive="yes" regex="no">Thread pid mismatch</output>
<output type="success" caseSensitive="yes" regex="no">do not match expected</output>
<output type="success" caseSensitive="yes" regex="no">Unable to create a thread:</output>
<!-- In the past, the failure below was caused by an issue where CRIU can't be found on the PATH. -->
<output type="failure" caseSensitive="yes" regex="no">Could not dump the JVM processes, err=-70</output>
<output type="success" caseSensitive="yes" regex="no">Restore arg: -Dprop1=val1</output>
<output type="success" caseSensitive="yes" regex="no">Restore arg: -Dprop2=val2</output>
<output type="success" caseSensitive="yes" regex="no">Restore arg: -Dprop3=val3</output>
</test>
<test id="Envvar test13">
<command>bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$" $MAINCLASS_ENVVAR_TEST$ EnvVarFileTest13 1</command>
<output type="success" caseSensitive="no" regex="no">Killed</output>
<output type="failure" caseSensitive="yes" regex="no">failed properties test</output>
<output type="required" caseSensitive="yes" regex="no">Pre-checkpoint</output>
<output type="success" caseSensitive="yes" regex="no">Failed to load options from the options file</output>
<output type="failure" caseSensitive="yes" regex="no">CRIU is not enabled</output>
<output type="failure" caseSensitive="yes" regex="no">Operation not permitted</output>
<!-- If CRIU can't acquire the original thread IDs, this test will fail. Nothing can be done about this failure. -->
<output type="success" caseSensitive="yes" regex="no">Thread pid mismatch</output>
<output type="success" caseSensitive="yes" regex="no">do not match expected</output>
<output type="success" caseSensitive="yes" regex="no">Unable to create a thread:</output>
<!-- In the past, the failure below was caused by an issue where CRIU can't be found on the PATH. -->
<output type="failure" caseSensitive="yes" regex="no">Could not dump the JVM processes, err=-70</output>
<output type="success" caseSensitive="yes" regex="no">org.eclipse.openj9.criu.JVMRestoreException</output>
</test>
<test id="Envvar test14">
<command>bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$" $MAINCLASS_ENVVAR_TEST$ EnvVarFileTest14 1</command>
<output type="success" caseSensitive="no" regex="no">Killed</output>
<output type="failure" caseSensitive="yes" regex="no">failed properties test</output>
<output type="required" caseSensitive="yes" regex="no">Pre-checkpoint</output>
<output type="success" caseSensitive="yes" regex="no">Failed to load options from the options file</output>
<output type="failure" caseSensitive="yes" regex="no">CRIU is not enabled</output>
<output type="failure" caseSensitive="yes" regex="no">Operation not permitted</output>
<!-- If CRIU can't acquire the original thread IDs, this test will fail. Nothing can be done about this failure. -->
<output type="success" caseSensitive="yes" regex="no">Thread pid mismatch</output>
<output type="success" caseSensitive="yes" regex="no">do not match expected</output>
<output type="success" caseSensitive="yes" regex="no">Unable to create a thread:</output>
<!-- In the past, the failure below was caused by an issue where CRIU can't be found on the PATH. -->
<output type="failure" caseSensitive="yes" regex="no">Could not dump the JVM processes, err=-70</output>
<output type="success" caseSensitive="yes" regex="no">org.eclipse.openj9.criu.JVMRestoreException</output>
</test>
<test id="Envvar test15">
<command>bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$" $MAINCLASS_ENVVAR_TEST$ EnvVarFileTest15 1</command>
<output type="success" caseSensitive="no" regex="no">Killed</output>
<output type="failure" caseSensitive="yes" regex="no">failed properties test</output>
<output type="required" caseSensitive="yes" regex="no">Pre-checkpoint</output>
<output type="success" caseSensitive="yes" regex="no">Failed to load options from the options file</output>
<output type="failure" caseSensitive="yes" regex="no">CRIU is not enabled</output>
<output type="failure" caseSensitive="yes" regex="no">Operation not permitted</output>
<!-- If CRIU can't acquire the original thread IDs, this test will fail. Nothing can be done about this failure. -->
<output type="success" caseSensitive="yes" regex="no">Thread pid mismatch</output>
<output type="success" caseSensitive="yes" regex="no">do not match expected</output>
<output type="success" caseSensitive="yes" regex="no">Unable to create a thread:</output>
<!-- In the past, the failure below was caused by an issue where CRIU can't be found on the PATH. -->
<output type="failure" caseSensitive="yes" regex="no">Could not dump the JVM processes, err=-70</output>
<output type="success" caseSensitive="yes" regex="no">org.eclipse.openj9.criu.JVMRestoreException</output>
</test>
<test id="Envvar test16">
<command>bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$" $MAINCLASS_ENVVAR_TEST$ EnvVarFileTest16 1</command>
<output type="success" caseSensitive="no" regex="no">Killed</output>
<output type="failure" caseSensitive="yes" regex="no">failed properties test</output>
<output type="required" caseSensitive="yes" regex="no">Pre-checkpoint</output>
<output type="success" caseSensitive="yes" regex="no">Failed to load options from the options file</output>
<output type="failure" caseSensitive="yes" regex="no">CRIU is not enabled</output>
<output type="failure" caseSensitive="yes" regex="no">Operation not permitted</output>
<!-- If CRIU can't acquire the original thread IDs, this test will fail. Nothing can be done about this failure. -->
<output type="success" caseSensitive="yes" regex="no">Thread pid mismatch</output>
<output type="success" caseSensitive="yes" regex="no">do not match expected</output>
<output type="success" caseSensitive="yes" regex="no">Unable to create a thread:</output>
<!-- In the past, the failure below was caused by an issue where CRIU can't be found on the PATH. -->
<output type="failure" caseSensitive="yes" regex="no">Could not dump the JVM processes, err=-70</output>
<output type="failure" caseSensitive="yes" regex="no">org.eclipse.openj9.criu.JVMRestoreException</output>
</test>
<test id="Restore trace options test with no trace options specified before checkpoint">
<command>bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$" $MAINCLASS_OPTIONSFILE_TEST$ TraceOptionsTest 1</command>
<output type="success" caseSensitive="no" regex="no">Killed</output>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,21 @@ public static void main(String[] args) {
case "EnvVarFileTest11":
envVarFileTest11();
break;
case "EnvVarFileTest12":
envVarFileTest12();
break;
case "EnvVarFileTest13":
envVarFileTest13();
break;
case "EnvVarFileTest14":
envVarFileTest14();
break;
case "EnvVarFileTest15":
envVarFileTest15();
break;
case "EnvVarFileTest16":
envVarFileTest16();
break;
default:
throw new RuntimeException("incorrect parameters");
}
Expand Down Expand Up @@ -330,4 +345,63 @@ static void envVarFileTest12() {
System.out.println("ERR: failed properties test");
}
}

static void envVarFileTest13() {
String optionsContents = RESTORE_ENV_VAR + "=-Xrs\n";
Path optionsFilePath = CRIUTestUtils.createOptionsFile("options", optionsContents);

Path imagePath = Paths.get("cpData");
CRIUTestUtils.createCheckpointDirectory(imagePath);
CRIUSupport criuSupport = new CRIUSupport(imagePath);
criuSupport.registerRestoreEnvFile(optionsFilePath);

System.out.println("Pre-checkpoint");
CRIUTestUtils.checkPointJVM(criuSupport, imagePath, true);
System.out.println("Post-checkpoint");
System.out.println("ERR: failed properties test");
}

static void envVarFileTest14() {
String optionsContents = RESTORE_ENV_VAR + "=-Xrs:sync\n";
Path optionsFilePath = CRIUTestUtils.createOptionsFile("options", optionsContents);

Path imagePath = Paths.get("cpData");
CRIUTestUtils.createCheckpointDirectory(imagePath);
CRIUSupport criuSupport = new CRIUSupport(imagePath);
criuSupport.registerRestoreEnvFile(optionsFilePath);

System.out.println("Pre-checkpoint");
CRIUTestUtils.checkPointJVM(criuSupport, imagePath, true);
System.out.println("Post-checkpoint");
System.out.println("ERR: failed properties test");
}

static void envVarFileTest15() {
String optionsContents = RESTORE_ENV_VAR + "=-Xrs:onRestore\n";
Path optionsFilePath = CRIUTestUtils.createOptionsFile("options", optionsContents);

Path imagePath = Paths.get("cpData");
CRIUTestUtils.createCheckpointDirectory(imagePath);
CRIUSupport criuSupport = new CRIUSupport(imagePath);
criuSupport.registerRestoreEnvFile(optionsFilePath);

System.out.println("Pre-checkpoint");
CRIUTestUtils.checkPointJVM(criuSupport, imagePath, true);
System.out.println("Post-checkpoint");
}

static void envVarFileTest16() {
String optionsContents = RESTORE_ENV_VAR + "=-Xrs:syncOnRestore\n";
Path optionsFilePath = CRIUTestUtils.createOptionsFile("options", optionsContents);

Path imagePath = Paths.get("cpData");
CRIUTestUtils.createCheckpointDirectory(imagePath);
CRIUSupport criuSupport = new CRIUSupport(imagePath);
criuSupport.registerRestoreEnvFile(optionsFilePath);

System.out.println("Pre-checkpoint");
CRIUTestUtils.checkPointJVM(criuSupport, imagePath, true);
System.out.println("Post-checkpoint");
}

}

0 comments on commit c29bc7e

Please sign in to comment.