From 56196e45eb51aeff9f79a11c23ad666265e92ba5 Mon Sep 17 00:00:00 2001 From: Dennis Hendriks Date: Sat, 8 Jun 2024 17:12:09 +0200 Subject: [PATCH] Add -norestart option to launcher. --- .../META-INF/MANIFEST.MF | 2 +- .../org/eclipse/equinox/app/IApplication.java | 12 +++- .../equinox/launcher/tests/LauncherTests.java | 41 ++++++++++++ .../feature.xml | 2 +- .../library/eclipse.c | 63 +++++++++++-------- .../library/eclipseCommon.h | 2 + 6 files changed, 94 insertions(+), 28 deletions(-) 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")