This is an automated email from the ASF dual-hosted git repository. lkishalmi pushed a commit to branch delivery in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/delivery by this push: new f556f4b Prevent race conditions during CLI install (#2523) f556f4b is described below commit f556f4b88826521d18181854f5ccd3be922a0283 Author: Svatopluk Dedic <svatopluk.de...@oracle.com> AuthorDate: Sun Nov 8 17:10:32 2020 +0100 Prevent race conditions during CLI install (#2523) * Use a special exitcode when connecting to CLI as client. Do not run upgrade step thereafter. * Piggyback with NBJLS server relaunch after installation completes. * Delay and/or disable the restart LSP client after connection termination with the hope to finish install tasks meanwhile and then restart explicitly * Wait after last child closes on Win. * Fixed launchers release number -> release. Co-authored-by: Jaroslav Tulach <jaroslav.tul...@oracle.com> --- .../nbcode/nbproject/genfiles.properties | 4 +- java/java.lsp.server/vscode/package.json | 6 +- java/java.lsp.server/vscode/src/extension.ts | 109 ++++++++++++++++++--- platform/o.n.bootstrap/external/binaries-list | 3 +- ...nse.txt => platform-launchers-12.2-license.txt} | 2 +- platform/o.n.bootstrap/launcher/unix/nbexec | 6 +- platform/o.n.bootstrap/launcher/windows/nbexec.cpp | 9 +- .../launcher/windows/platformlauncher.cpp | 9 +- .../o.n.bootstrap/nbproject/project.properties | 8 +- .../o.n.bootstrap/src/org/netbeans/CLIHandler.java | 1 + .../o.n.bootstrap/src/org/netbeans/MainImpl.java | 2 +- 11 files changed, 131 insertions(+), 28 deletions(-) diff --git a/java/java.lsp.server/nbcode/nbproject/genfiles.properties b/java/java.lsp.server/nbcode/nbproject/genfiles.properties index d7a1e40..48caec6 100644 --- a/java/java.lsp.server/nbcode/nbproject/genfiles.properties +++ b/java/java.lsp.server/nbcode/nbproject/genfiles.properties @@ -3,9 +3,9 @@ build.xml.script.CRC32=95ec0861 build.xml.stylesheet.CRC32=70ce5c94@2.80 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=99f9616a +nbproject/build-impl.xml.data.CRC32=48c0390b nbproject/build-impl.xml.script.CRC32=e03e5352 -nbproject/build-impl.xml.stylesheet.CRC32=473dc988@2.80 +nbproject/build-impl.xml.stylesheet.CRC32=473dc988@2.82 nbproject/platform.xml.data.CRC32=99f9616a nbproject/platform.xml.script.CRC32=6dcbd131 nbproject/platform.xml.stylesheet.CRC32=ae64f0b6@2.80 diff --git a/java/java.lsp.server/vscode/package.json b/java/java.lsp.server/vscode/package.json index 5b51355..963da4d 100644 --- a/java/java.lsp.server/vscode/package.json +++ b/java/java.lsp.server/vscode/package.json @@ -46,9 +46,9 @@ "default": false, "description": "Enables verbose messages from the Apache NetBeans Language Server" }, - "netbeans.conflict.check" : { - "type" : "boolean", - "default" : true, + "netbeans.conflict.check": { + "type": "boolean", + "default": true, "description": "Avoid conflicts with other Java extensions" }, "java.test.editor.enableShortcuts": { diff --git a/java/java.lsp.server/vscode/src/extension.ts b/java/java.lsp.server/vscode/src/extension.ts index 7a3df78..2981f72 100644 --- a/java/java.lsp.server/vscode/src/extension.ts +++ b/java/java.lsp.server/vscode/src/extension.ts @@ -168,13 +168,73 @@ export function activate(context: ExtensionContext) { })); } +/** + * Pending maintenance (install) task, activations should be chained after it. + */ +let maintenance : Promise<void> | null; + +/** + * Pending activation flag. Will be cleared when the process produces some message or fails. + */ +let activationPending : boolean = false; + function activateWithJDK(specifiedJDK: string | null, context: ExtensionContext, log : vscode.OutputChannel, notifyKill: boolean): void { - if (nbProcess) { + const a : Promise<void> | null = maintenance; + if (activationPending) { + // do not activate more than once in parallel. + console.log("Server activation requested repeatedly, ignoring..."); + return; + } + activationPending = true; + // chain the restart after termination of the former process. + if (a != null) { + console.log("Server activation initiated while in maintenance mode, scheduling after maintenance"); + a.then(() => killNbProcess(notifyKill, log)). + then(() => doActivateWithJDK(specifiedJDK, context, log, notifyKill)); + } else { + console.log("Initiating server activation"); + killNbProcess(notifyKill, log).then( + () => doActivateWithJDK(specifiedJDK, context, log, notifyKill) + ); + } +} + +function killNbProcess(notifyKill : boolean, log : vscode.OutputChannel, specProcess?: ChildProcess) : Promise<void> { + const p = nbProcess; + console.log("Request to kill LSP server."); + if (p && (!specProcess || specProcess == p)) { if (notifyKill) { vscode.window.setStatusBarMessage("Restarting Apache NetBeans Language Server.", 2000); } - nbProcess.kill(); + return new Promise((resolve, reject) => { + nbProcess = null; + p.on('close', function(code: number) { + console.log("LSP server closed: " + p.pid) + resolve(); + }); + console.log("Killing LSP server " + p.pid); + if (!p.kill()) { + reject("Cannot kill"); + } + }); + } else { + let msg = "Cannot kill: "; + if (specProcess) { + msg += "Requested kill on " + specProcess.pid + ", "; + } + console.log(msg + "current process is " + (p ? p.pid : "None")); + return new Promise((res, rej) => { res(); }); } +} + +function doActivateWithJDK(specifiedJDK: string | null, context: ExtensionContext, log : vscode.OutputChannel, notifyKill: boolean): void { + maintenance = null; + let restartWithJDKLater : ((time: number, n: boolean) => void) = function restartLater(time: number, n : boolean) { + log.appendLine(`Restart of Apache Language Server requested in ${(time / 1000)} s.`); + setTimeout(() => { + activateWithJDK(specifiedJDK, context, log, n); + }, time); + }; const beVerbose : boolean = workspace.getConfiguration('netbeans').get('verbose', false); let info = { @@ -184,7 +244,6 @@ function activateWithJDK(specifiedJDK: string | null, context: ExtensionContext, jdkHome : specifiedJDK, verbose: beVerbose }; - let launchMsg = `Launching Apache NetBeans Language Server with ${specifiedJDK ? specifiedJDK : 'default system JDK'}`; log.appendLine(launchMsg); vscode.window.setStatusBarMessage(launchMsg, 2000); @@ -192,6 +251,7 @@ function activateWithJDK(specifiedJDK: string | null, context: ExtensionContext, let ideRunning = new Promise((resolve, reject) => { let collectedText : string | null = ''; function logAndWaitForEnabled(text: string) { + activationPending = false; log.append(text); if (collectedText == null) { return; @@ -203,6 +263,7 @@ function activateWithJDK(specifiedJDK: string | null, context: ExtensionContext, } } let p = launcher.launch(info, "--modules", "--list"); + console.log("LSP server launching: " + p.pid); p.stdout.on('data', function(d: any) { logAndWaitForEnabled(d.toString()); }); @@ -210,8 +271,8 @@ function activateWithJDK(specifiedJDK: string | null, context: ExtensionContext, logAndWaitForEnabled(d.toString()); }); nbProcess = p; - nbProcess.on('close', function(code: number) { - if (p == nbProcess && code != 0) { + p.on('close', function(code: number) { + if (p == nbProcess && code != 0 && code) { vscode.window.showWarningMessage("Apache NetBeans Language Server exited with " + code); } if (collectedText != null) { @@ -222,8 +283,10 @@ function activateWithJDK(specifiedJDK: string | null, context: ExtensionContext, log.appendLine("Cannot find org.netbeans.modules.java.lsp.server in the log!"); } log.show(false); + killNbProcess(false, log, p); reject("Apache NetBeans Language Server not enabled!"); } else { + console.log("LSP server " + p.pid + " terminated with " + code); log.appendLine("Exit code " + code); } }); @@ -293,7 +356,8 @@ function activateWithJDK(specifiedJDK: string | null, context: ExtensionContext, return ErrorAction.Continue; }, closed : function(): CloseAction { - activateWithJDK(specifiedJDK, context, log, false); + log.appendLine("Connection to Apache NetBeans Language Server closed."); + restartWithJDKLater(10000, false); return CloseAction.DoNotRestart; } } @@ -314,6 +378,7 @@ function activateWithJDK(specifiedJDK: string | null, context: ExtensionContext, client.onNotification(StatusMessageRequest.type, showStatusBarMessage); }); }).catch((reason) => { + activationPending = false; log.append(reason); window.showErrorMessage('Error initializing ' + reason); }); @@ -351,14 +416,32 @@ function activateWithJDK(specifiedJDK: string | null, context: ExtensionContext, const yes = "Install GPLv2+CPEx code"; window.showErrorMessage("Additional Java Support is needed", yes).then(reply => { if (yes === reply) { - let installProcess = launcher.launch(info, "--modules", "--install", ".*nbjavac.*"); - let logData = function(d: any) { - log.append(d.toString()); + vscode.window.setStatusBarMessage("Preparing Apache NetBeans Language Server for additional installation", 2000); + restartWithJDKLater = function() { + console.log("Ignoring request for restart of Apache NetBeans Language Server"); }; - installProcess.stdout.on('data', logData); - installProcess.stderr.on('data', logData); - installProcess.on('close', function(code: number) { - log.append("Additional Java Support installed with exit code " + code); + maintenance = new Promise((resolve, reject) => { + const kill : Promise<void> = killNbProcess(false, log); + kill.then(() => { + let installProcess = launcher.launch(info, "-J-Dnetbeans.close=true", "--modules", "--install", ".*nbjavac.*"); + console.log("Launching installation process: " + installProcess.pid); + let logData = function(d: any) { + log.append(d.toString()); + }; + installProcess.stdout.on('data', logData); + installProcess.stderr.on('data', logData); + installProcess.addListener("error", reject); + // MUST wait on 'close', since stdout is inherited by children. The installProcess dies but + // the inherited stream will be closed by the last child dying. + installProcess.on('close', function(code: number) { + console.log("Installation completed: " + installProcess.pid); + log.appendLine("Additional Java Support installed with exit code " + code); + // will be actually run after maintenance is resolve()d. + activateWithJDK(specifiedJDK, context, log, notifyKill) + resolve(); + }); + return installProcess; + }); }); } }); diff --git a/platform/o.n.bootstrap/external/binaries-list b/platform/o.n.bootstrap/external/binaries-list index 511ab38..99132f1 100644 --- a/platform/o.n.bootstrap/external/binaries-list +++ b/platform/o.n.bootstrap/external/binaries-list @@ -14,4 +14,5 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -3289B87AB9345958E16F3285ED884F5C4DAB7C2D platform-launchers-10.0.zip +0879C497EA45DF57BFF833A45AE9217FA447C713 platform-launchers-12.2.zip + diff --git a/platform/o.n.bootstrap/external/platform-launchers-10.0-license.txt b/platform/o.n.bootstrap/external/platform-launchers-12.2-license.txt similarity index 99% rename from platform/o.n.bootstrap/external/platform-launchers-10.0-license.txt rename to platform/o.n.bootstrap/external/platform-launchers-12.2-license.txt index b57feb7..c2ad62b 100644 --- a/platform/o.n.bootstrap/external/platform-launchers-10.0-license.txt +++ b/platform/o.n.bootstrap/external/platform-launchers-12.2-license.txt @@ -1,6 +1,6 @@ Name: NetBeans Application Launchers Description: Windows Launchers for the NetBeans Platform -Version: 10.0 +Version: 12.2 License: Apache-2.0 Source: https://netbeans.org/ Origin: NetBeans diff --git a/platform/o.n.bootstrap/launcher/unix/nbexec b/platform/o.n.bootstrap/launcher/unix/nbexec old mode 100644 new mode 100755 index ca7d16b..f59096a --- a/platform/o.n.bootstrap/launcher/unix/nbexec +++ b/platform/o.n.bootstrap/launcher/unix/nbexec @@ -433,6 +433,11 @@ while [ "$restart" ] ; do trap '' EXIT look_for_new_clusters # If we should update anything, do it and restart IDE. + if [ $exitcode -eq 4 ] ; then + # Just connected to CLI, not in charge of running Updater or whatever. + exitcode=0 + break + fi run_updater="" look_for_post_runs "$plathome" @@ -454,6 +459,5 @@ while [ "$restart" ] ; do fi done - # and we exit. exit $exitcode diff --git a/platform/o.n.bootstrap/launcher/windows/nbexec.cpp b/platform/o.n.bootstrap/launcher/windows/nbexec.cpp index 2e63d02..47e490e 100644 --- a/platform/o.n.bootstrap/launcher/windows/nbexec.cpp +++ b/platform/o.n.bootstrap/launcher/windows/nbexec.cpp @@ -43,9 +43,16 @@ extern "C" BOOL APIENTRY DllMain(HANDLE hModule, return TRUE; } +volatile int exitStatus = 0; + void exitHook(int status) { + exitStatus = status; logMsg("Exit hook called with status %d", status); - launcher.onExit(); + // do not handle possible restarts, if we are just CLI-connecting to a running process. + if (status != -252) { + launcher.onExit(); + } + logMsg("Exit hook terminated."); } #define NBEXEC_EXPORT extern "C" __declspec(dllexport) diff --git a/platform/o.n.bootstrap/launcher/windows/platformlauncher.cpp b/platform/o.n.bootstrap/launcher/windows/platformlauncher.cpp index b29b309..8df954c 100644 --- a/platform/o.n.bootstrap/launcher/windows/platformlauncher.cpp +++ b/platform/o.n.bootstrap/launcher/windows/platformlauncher.cpp @@ -24,6 +24,8 @@ #include "platformlauncher.h" #include "argnames.h" +volatile extern int exitStatus; + using namespace std; const char *PlatformLauncher::HELP_MSG = @@ -662,6 +664,10 @@ bool PlatformLauncher::restartRequested() { void PlatformLauncher::onExit() { logMsg("onExit()"); + if (exitStatus == -252) { + logMsg("Exiting from CLI client, will not restart."); + return; + } if (exiting) { logMsg("Already exiting, no need to schedule restart"); @@ -714,7 +720,8 @@ void PlatformLauncher::onExit() { STARTUPINFO si = {0}; PROCESS_INFORMATION pi = {0}; si.cb = sizeof(STARTUPINFO); - if (!CreateProcess(NULL, cmdLineStr, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { + + if (!CreateProcess(NULL, cmdLineStr, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { logErr(true, true, "Failed to create process."); return; } diff --git a/platform/o.n.bootstrap/nbproject/project.properties b/platform/o.n.bootstrap/nbproject/project.properties index e10ee5b..83ac777 100644 --- a/platform/o.n.bootstrap/nbproject/project.properties +++ b/platform/o.n.bootstrap/nbproject/project.properties @@ -20,10 +20,10 @@ javac.source=1.8 module.jar.dir=lib module.jar.basename=boot.jar release.launcher/unix/nbexec=lib/nbexec -release.external/platform-launchers-10.0.zip!/nbexec.exe=lib/nbexec.exe -release.external/platform-launchers-10.0.zip!/nbexec64.exe=lib/nbexec64.exe -release.external/platform-launchers-10.0.zip!/nbexec.dll=lib/nbexec.dll -release.external/platform-launchers-10.0.zip!/nbexec64.dll=lib/nbexec64.dll +release.external/platform-launchers-12.2.zip!/nbexec.exe=lib/nbexec.exe +release.external/platform-launchers-12.2.zip!/nbexec64.exe=lib/nbexec64.exe +release.external/platform-launchers-12.2.zip!/nbexec.dll=lib/nbexec.dll +release.external/platform-launchers-12.2.zip!/nbexec64.dll=lib/nbexec64.dll nbm.executable.files=lib/nbexec javadoc.arch=${basedir}/arch.xml diff --git a/platform/o.n.bootstrap/src/org/netbeans/CLIHandler.java b/platform/o.n.bootstrap/src/org/netbeans/CLIHandler.java index ebd7f2e..5e2bf4a 100644 --- a/platform/o.n.bootstrap/src/org/netbeans/CLIHandler.java +++ b/platform/o.n.bootstrap/src/org/netbeans/CLIHandler.java @@ -258,6 +258,7 @@ public abstract class CLIHandler extends Object { public static final int CANNOT_CONNECT = -255; public static final int CANNOT_WRITE = -254; public static final int ALREADY_RUNNING = -253; + public static final int CONNECTED = -252; private final File lockFile; private final int port; diff --git a/platform/o.n.bootstrap/src/org/netbeans/MainImpl.java b/platform/o.n.bootstrap/src/org/netbeans/MainImpl.java index 577c392..b812f97 100644 --- a/platform/o.n.bootstrap/src/org/netbeans/MainImpl.java +++ b/platform/o.n.bootstrap/src/org/netbeans/MainImpl.java @@ -60,7 +60,7 @@ final class MainImpl extends Object { int res = execute (args, System.in, System.out, System.err, m); if (res == -1) { // Connected to another running NB instance and succeeded in making a call. - return; + System.exit(CLIHandler.Status.CONNECTED); } else if (res != 0) { // Some CLIHandler refused the invocation if (res == Integer.MIN_VALUE) { --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org For additional commands, e-mail: commits-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists