diff --git a/bundles/org.eclipse.equinox.app/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.app/META-INF/MANIFEST.MF
index 5b5da69a985..cc457569fac 100644
--- a/bundles/org.eclipse.equinox.app/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.app/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.equinox.app; singleton:=true
-Bundle-Version: 1.7.100.qualifier
+Bundle-Version: 1.7.200.qualifier
Bundle-Vendor: %providerName
Bundle-Activator: org.eclipse.equinox.internal.app.Activator
Bundle-Localization: plugin
diff --git a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/app/IApplication.java b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/app/IApplication.java
index 08c257f8f80..77c83033802 100644
--- a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/app/IApplication.java
+++ b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/app/IApplication.java
@@ -34,7 +34,12 @@ public interface IApplication {
public static final Integer EXIT_OK = Integer.valueOf(0);
/**
- * Exit object requesting platform restart
+ * Exit object requesting platform restart.
+ *
+ *
+ * Note: The handling of this special exit code may be disabled by launcher
+ * argument '-norestart'.
+ *
*/
public static final Integer EXIT_RESTART = Integer.valueOf(23);
@@ -44,6 +49,11 @@ public interface IApplication {
* the executable is relaunched the command line will be retrieved from the
* {@link IApplicationContext#EXIT_DATA_PROPERTY eclipse.exitdata} system
* property.
+ *
+ *
+ * Note: The handling of this special exit code may be disabled by launcher
+ * argument '-norestart'.
+ *
*/
public static final Integer EXIT_RELAUNCH = Integer.valueOf(24);
diff --git a/bundles/org.eclipse.equinox.launcher.tests/src/org/eclipse/equinox/launcher/tests/LauncherTests.java b/bundles/org.eclipse.equinox.launcher.tests/src/org/eclipse/equinox/launcher/tests/LauncherTests.java
index 18531352f68..cde3fc34754 100644
--- a/bundles/org.eclipse.equinox.launcher.tests/src/org/eclipse/equinox/launcher/tests/LauncherTests.java
+++ b/bundles/org.eclipse.equinox.launcher.tests/src/org/eclipse/equinox/launcher/tests/LauncherTests.java
@@ -16,6 +16,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
import java.io.BufferedReader;
import java.io.DataOutputStream;
@@ -23,6 +24,7 @@
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
+import java.net.SocketTimeoutException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -204,6 +206,45 @@ void test_appTerminatesWithCodeZeroOnExit() throws IOException, InterruptedExcep
assertEquals(0, launcherProcess.exitValue());
}
+ @Test
+ void test_appTerminatesWithNoRestartAndEXIT_OK() throws IOException, InterruptedException {
+ test_norestart(EXIT_OK);
+ }
+
+ @Test
+ void test_appTerminatesWithNoRestartAndEXIT_RESTART() throws IOException, InterruptedException {
+ test_norestart(EXIT_RESTART);
+ }
+
+ @Test
+ void test_appTerminatesWithNoRestartAndEXIT_RELAUNCH() throws IOException, InterruptedException {
+ test_norestart(EXIT_RELAUNCH);
+ }
+
+ private void test_norestart(int exitCode) throws IOException, InterruptedException {
+ writeEclipseIni(DEFAULT_ECLIPSE_INI_CONTENT);
+
+ Process launcherProcess = startEclipseLauncher(List.of("-norestart"));
+
+ Socket socket = server.accept();
+
+ List appArgs = new ArrayList<>();
+ analyzeLaunchedTestApp(socket, appArgs, null, exitCode);
+
+ // Make sure -norestart arg is picked
+ assertTrue(appArgs.contains("--launcher.noRestart"));
+ // Make sure launcher exited with expected exit value
+ launcherProcess.waitFor(5, TimeUnit.SECONDS);
+ assertEquals(exitCode, launcherProcess.exitValue());
+ try {
+ server.accept();
+ fail("New eclipse started even with -norestart arg and exit code " + exitCode);
+ } catch (SocketTimeoutException e) {
+ // No new instance launched
+ return;
+ }
+ }
+
@Test
void test_eclipseIniChangesShouldBePickedOnRestart() throws IOException {
writeEclipseIni(DEFAULT_ECLIPSE_INI_CONTENT);
diff --git a/features/org.eclipse.equinox.compendium.sdk/feature.xml b/features/org.eclipse.equinox.compendium.sdk/feature.xml
index fbc6b4f0110..f4ea7f32447 100644
--- a/features/org.eclipse.equinox.compendium.sdk/feature.xml
+++ b/features/org.eclipse.equinox.compendium.sdk/feature.xml
@@ -2,7 +2,7 @@
diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipse.c b/features/org.eclipse.equinox.executable.feature/library/eclipse.c
index c7cf694182b..f397bf83d3e 100644
--- a/features/org.eclipse.equinox.executable.feature/library/eclipse.c
+++ b/features/org.eclipse.equinox.executable.feature/library/eclipse.c
@@ -71,6 +71,7 @@
* -nosplash do not display the splash screen. The java application will
* not receive the -showsplash command.
* -showsplash show the given bitmap in the splash screen.
+ * -norestart disables the restart behavior of exit codes 23 and 24.
* -name application name displayed in error message dialogs and
* splash screen window. Default value is computed from the
* name of the executable - with the first letter capitalized
@@ -235,6 +236,7 @@ home directory.");
static int needConsole = 0; /* True: user wants a console */
static int debug = 0; /* True: output debugging info */
static int noSplash = 0; /* True: do not show splash win */
+static int noRestart = 0; /* True: disables the restart behavior of the launcher */
static int suppressErrors = 0; /* True: do not display errors dialogs */
int secondThread = 0; /* True: start the VM on a second thread */
static int appendVmargs = 0; /* True: append cmdline vmargs to launcher.ini vmargs */
@@ -286,6 +288,7 @@ static Option options[] = {
{ CONSOLELOG, &needConsole, VALUE_IS_FLAG, 0 },
{ DEBUG_ARG, &debug, VALUE_IS_FLAG, 0 },
{ NOSPLASH, &noSplash, VALUE_IS_FLAG, 1 },
+ { NORESTART, &noRestart, VALUE_IS_FLAG, 1 },
{ SUPRESSERRORS, &suppressErrors, VALUE_IS_FLAG, 1},
{ SECOND_THREAD, &secondThread, VALUE_IS_FLAG, 1 },
{ APPEND_VMARGS, &appendVmargs, VALUE_IS_FLAG, 1 },
@@ -650,29 +653,32 @@ static int _run(int argc, _TCHAR* argv[], _TCHAR* vmArgs[])
case 0: /* normal exit */
break;
case RESTART_LAST_EC:
- /* copy for relaunch, +1 to ensure NULL terminated */
- relaunchCommand = malloc((initialArgc + 1) * sizeof(_TCHAR*));
- memcpy(relaunchCommand, initialArgv, (initialArgc + 1) * sizeof(_TCHAR*));
- relaunchCommand[initialArgc] = 0;
- relaunchCommand[0] = program;
+ if (!noRestart) {
+ /* copy for relaunch, +1 to ensure NULL terminated */
+ relaunchCommand = malloc((initialArgc + 1) * sizeof(_TCHAR*));
+ memcpy(relaunchCommand, initialArgv, (initialArgc + 1) * sizeof(_TCHAR*));
+ relaunchCommand[initialArgc] = 0;
+ relaunchCommand[0] = program;
+ }
break;
-
case RESTART_NEW_EC:
- if(launchMode == LAUNCH_EXE) {
- if (exitData != NULL) free(exitData);
- if (getSharedData( sharedID, &exitData ) != 0)
- exitData = NULL;
- }
- if (exitData != 0) {
- if (vmCommand != NULL) free( vmCommand );
- vmCommand = parseArgList( exitData );
- relaunchCommand = getRelaunchCommand(vmCommand);
- } else {
- if (debug) {
- if (!suppressErrors)
- displayMessage( officialName, shareMsg );
- else
- _ftprintf(stderr, _T_ECLIPSE("%s:\n%s\n"), officialName, shareMsg);
+ if (!noRestart) {
+ if(launchMode == LAUNCH_EXE) {
+ if (exitData != NULL) free(exitData);
+ if (getSharedData( sharedID, &exitData ) != 0)
+ exitData = NULL;
+ }
+ if (exitData != 0) {
+ if (vmCommand != NULL) free( vmCommand );
+ vmCommand = parseArgList( exitData );
+ relaunchCommand = getRelaunchCommand(vmCommand);
+ } else {
+ if (debug) {
+ if (!suppressErrors)
+ displayMessage( officialName, shareMsg );
+ else
+ _ftprintf(stderr, _T_ECLIPSE("%s:\n%s\n"), officialName, shareMsg);
+ }
}
}
break;
@@ -1103,12 +1109,15 @@ static void getVMCommand( int launchMode, int argc, _TCHAR* argv[], _TCHAR **vmA
(*vmArgv)[dst] = NULL;
/* Program arguments */
- /* OS + WS + ARCH + LAUNCHER + NAME +
- * + LIBRARY + SHOWSPLASH + EXITDATA + STARTUP + OVERRIDE/APPEND + argv[] + VM + +
- * VMARGS + vmArg + requiredVMargs
+ /* OS + WS + ARCH + SHOWSPLASH + LAUNCHER + NAME
+ * + LIBRARY + STARTUP + PROTECT + APPEND/OVERRIDE + NORESTART
+ * + EXITDATA + argv[] + VM + VMARGS + vmArg[] + eeVMarg[] + reqVMarg[]
* + NULL)
*/
- totalProgArgs = 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 1 + argc + 2 + 1 + nVMarg + nEEargs + nReqVMarg + 1;
+ totalProgArgs = 2 + 2 + 2 + 2 + 2 + 2
+ + 2 + 2 + 2 + 1 + 1
+ + 2 + argc + 2 + 1 + nVMarg + nEEargs + nReqVMarg
+ + 1;
*progArgv = malloc( totalProgArgs * sizeof( _TCHAR* ) );
dst = 0;
@@ -1157,6 +1166,10 @@ static void getVMCommand( int launchMode, int argc, _TCHAR* argv[], _TCHAR **vmA
/* override or append vm args */
(*progArgv)[ dst++ ] = appendVmargs ? APPEND_VMARGS : OVERRIDE_VMARGS;
+ /* 'No restart' argument, if applicable. */
+ if (noRestart)
+ (*progArgv)[ dst++ ] = LAUNCHER_NORESTART;
+
/* Append the exit data command. */
if (sharedID) {
(*progArgv)[ dst++ ] = EXITDATA;
diff --git a/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.h b/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.h
index 07dc45c5dc9..41097c6b98a 100644
--- a/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.h
+++ b/features/org.eclipse.equinox.executable.feature/library/eclipseCommon.h
@@ -25,6 +25,7 @@
#define OS _T_ECLIPSE("-os")
#define OSARCH _T_ECLIPSE("-arch")
#define NOSPLASH _T_ECLIPSE("-nosplash")
+#define NORESTART _T_ECLIPSE("-norestart")
#define LAUNCHER _T_ECLIPSE("-launcher")
#define SHOWSPLASH _T_ECLIPSE("-showsplash")
#define EXITDATA _T_ECLIPSE("-exitdata")
@@ -47,6 +48,7 @@
#define INI _T_ECLIPSE("--launcher.ini")
#define APPEND_VMARGS _T_ECLIPSE("--launcher.appendVmargs")
#define OVERRIDE_VMARGS _T_ECLIPSE("--launcher.overrideVmargs")
+#define LAUNCHER_NORESTART _T_ECLIPSE("--launcher.noRestart")
#define SECOND_THREAD _T_ECLIPSE("--launcher.secondThread")
#define PERM_GEN _T_ECLIPSE("--launcher.XXMaxPermSize")
#define OLD_ARGS_START _T_ECLIPSE("--launcher.oldUserArgsStart")