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

Reply via email to