Browse Source

:art: 改进桌面端拉起内核 https://github.com/siyuan-note/siyuan/issues/6894

Liang Ding 2 years ago
parent
commit
1715b150a2
3 changed files with 56 additions and 49 deletions
  1. 46 45
      app/electron/main.js
  2. 2 2
      app/pnpm-lock.yaml
  3. 8 2
      kernel/util/working.go

+ 46 - 45
app/electron/main.js

@@ -34,7 +34,6 @@ const isDevEnv = process.env.NODE_ENV === 'development'
 const appVer = app.getVersion()
 const appVer = app.getVersion()
 const confDir = path.join(app.getPath('home'), '.config', 'siyuan')
 const confDir = path.join(app.getPath('home'), '.config', 'siyuan')
 const windowStatePath = path.join(confDir, 'windowState.json')
 const windowStatePath = path.join(confDir, 'windowState.json')
-const portJSONPath = path.join(confDir, 'port.json')
 let tray // 托盘必须使用全局变量,以防止被垃圾回收 https://www.electronjs.org/docs/faq#my-apps-windowtray-disappeared-after-a-few-minutes
 let tray // 托盘必须使用全局变量,以防止被垃圾回收 https://www.electronjs.org/docs/faq#my-apps-windowtray-disappeared-after-a-few-minutes
 let mainWindow // 从托盘处激活报错 https://github.com/siyuan-note/siyuan/issues/769
 let mainWindow // 从托盘处激活报错 https://github.com/siyuan-note/siyuan/issues/769
 let firstOpenWindow, bootWindow
 let firstOpenWindow, bootWindow
@@ -42,7 +41,6 @@ let closeButtonBehavior = 0
 let siyuanOpenURL
 let siyuanOpenURL
 let firstOpen = false
 let firstOpen = false
 let resetWindowStateOnRestart = false
 let resetWindowStateOnRestart = false
-let kernelPort = "6806"
 const localhost = "127.0.0.1"
 const localhost = "127.0.0.1"
 require('@electron/remote/main').initialize()
 require('@electron/remote/main').initialize()
 
 
@@ -51,10 +49,6 @@ if (!app.requestSingleInstanceLock()) {
   return
   return
 }
 }
 
 
-const getServer = () => {
-  return "http://" + localhost + ":" + kernelPort
-}
-
 const showErrorWindow = (title, content) => {
 const showErrorWindow = (title, content) => {
   let errorHTMLPath = path.join(appDir, 'app', 'electron', 'error.html')
   let errorHTMLPath = path.join(appDir, 'app', 'electron', 'error.html')
   if (isDevEnv) {
   if (isDevEnv) {
@@ -554,6 +548,46 @@ const boot = () => {
   }
   }
 }
 }
 
 
+let kernelPort = 6806
+let tryGetPortCount = 0
+const net = require("net");
+const getAvailablePort = (port = kernelPort) => {
+  // https://gist.github.com/mikeal/1840641
+
+  const server = net.createServer()
+  return new Promise((resolve, reject) => server
+    .on('error', error => {
+      writeLog(error)
+      if (2048 < ++tryGetPortCount) {
+        writeLog('failed to get available port [tryCount=' + tryGetPortCount + ', port=' + port + ']')
+        reject(error)
+        return
+      }
+      server.listen(++port)
+    })
+    .on('listening', () => {
+      writeLog('found an available port [' + port + ']')
+      server.close(() => resolve(port))
+    })
+    .listen(port, '127.0.0.1'))
+}
+
+const getKernelPort = async () => {
+  if (isDevEnv) {
+    writeLog("got kernel port [" + kernelPort + "]")
+    return kernelPort
+  }
+
+  // 改进桌面端拉起内核 https://github.com/siyuan-note/siyuan/issues/6894
+  kernelPort = await getAvailablePort()
+  writeLog("got kernel available port [" + kernelPort + "]")
+  return kernelPort
+}
+
+const getServer = () => {
+  return "http://" + localhost + ":" + kernelPort
+}
+
 const initKernel = (initData) => {
 const initKernel = (initData) => {
   return new Promise(async (resolve) => {
   return new Promise(async (resolve) => {
     bootWindow = new BrowserWindow({
     bootWindow = new BrowserWindow({
@@ -577,7 +611,8 @@ const initKernel = (initData) => {
       return
       return
     }
     }
 
 
-    const cmds = ['--wd', appDir]
+    const availablePort = await getKernelPort()
+    const cmds = ['--port', availablePort, '--wd', appDir]
     if (isDevEnv) {
     if (isDevEnv) {
       cmds.push('--mode', 'dev')
       cmds.push('--mode', 'dev')
     }
     }
@@ -639,44 +674,6 @@ const initKernel = (initData) => {
       })
       })
     }
     }
 
 
-    const getKernelPort = async () => {
-      if (isDevEnv) {
-        return kernelPort
-      }
-
-      await sleep(200)
-      let gotPort = false
-      let count = 0
-      while (!gotPort) {
-        try {
-          const portJSON = JSON.parse(fs.readFileSync(portJSONPath, 'utf8'))
-          const ret = portJSON[kernelProcessPid]
-          if (ret) {
-            gotPort = true
-            return ret
-          }
-          await sleep(100)
-        } catch (e) {
-          await sleep(100)
-        } finally {
-          count++
-          if (64 < count) {
-            writeLog('get kernel port failed [pid=' + kernelProcessPid + ']')
-            return
-          }
-        }
-      }
-    }
-
-    kernelPort = await getKernelPort()
-    if (!kernelPort) {
-      showErrorWindow('⚠️ 获取内核服务端口失败 Failed to get kernel serve port',
-        '<div>获取内核服务端口失败,请确保程序拥有网络权限并不受防火墙和杀毒软件阻止。</div><div>Failed to get kernel serve port, please make sure the program has network permissions and is not blocked by firewalls and antivirus software.</div>')
-      bootWindow.destroy()
-      resolve(false)
-    }
-    writeLog("got kernel port [" + kernelPort + "]")
-
     let gotVersion = false
     let gotVersion = false
     let apiData
     let apiData
     let count = 0
     let count = 0
@@ -696,8 +693,12 @@ const initKernel = (initData) => {
         count++
         count++
         if (14 < count) {
         if (14 < count) {
           writeLog('get kernel ver failed')
           writeLog('get kernel ver failed')
+
+          showErrorWindow('⚠️ 获取内核服务端口失败 Failed to get kernel serve port',
+            '<div>获取内核服务端口失败,请确保程序拥有网络权限并不受防火墙和杀毒软件阻止。</div><div>Failed to get kernel serve port, please make sure the program has network permissions and is not blocked by firewalls and antivirus software.</div>')
           bootWindow.destroy()
           bootWindow.destroy()
           resolve(false)
           resolve(false)
+          return
         }
         }
       }
       }
     }
     }

+ 2 - 2
app/pnpm-lock.yaml

@@ -1928,10 +1928,10 @@ packages:
     resolution: {integrity: sha512-m0+M53+HYMzqKxwNQZT143K7WwXEGUy9LY31l8dJphXx2P/FQod615mVbxHyqbDCG4J5bHdWm21qZ0e2DVY6CQ==}
     resolution: {integrity: sha512-m0+M53+HYMzqKxwNQZT143K7WwXEGUy9LY31l8dJphXx2P/FQod615mVbxHyqbDCG4J5bHdWm21qZ0e2DVY6CQ==}
     engines: {node: '>=14.0.0'}
     engines: {node: '>=14.0.0'}
     dependencies:
     dependencies:
+      7zip-bin: 5.1.1
       '@develar/schema-utils': 2.6.5
       '@develar/schema-utils': 2.6.5
       '@electron/universal': 1.2.1
       '@electron/universal': 1.2.1
       '@malept/flatpak-bundler': 0.4.0
       '@malept/flatpak-bundler': 0.4.0
-      7zip-bin: 5.1.1
       async-exit-hook: 2.0.1
       async-exit-hook: 2.0.1
       bluebird-lst: 1.0.9
       bluebird-lst: 1.0.9
       builder-util: 23.3.3
       builder-util: 23.3.3
@@ -2215,9 +2215,9 @@ packages:
   /builder-util/23.3.3:
   /builder-util/23.3.3:
     resolution: {integrity: sha512-MJZlUiq2PY5hjYv9+XNaoYdsITqvLgRDoHSFg/4nzpInbNxNjLQOolL04Zsyp+hgfcbFvMC4h0KkR1CMPHLWbA==}
     resolution: {integrity: sha512-MJZlUiq2PY5hjYv9+XNaoYdsITqvLgRDoHSFg/4nzpInbNxNjLQOolL04Zsyp+hgfcbFvMC4h0KkR1CMPHLWbA==}
     dependencies:
     dependencies:
+      7zip-bin: 5.1.1
       '@types/debug': 4.1.7
       '@types/debug': 4.1.7
       '@types/fs-extra': 9.0.13
       '@types/fs-extra': 9.0.13
-      7zip-bin: 5.1.1
       app-builder-bin: 4.0.0
       app-builder-bin: 4.0.0
       bluebird-lst: 1.0.9
       bluebird-lst: 1.0.9
       builder-util-runtime: 9.0.3
       builder-util-runtime: 9.0.3

+ 8 - 2
kernel/util/working.go

@@ -446,10 +446,16 @@ func GetDataAssetsAbsPath() (ret string) {
 
 
 func tryLockWorkspace() {
 func tryLockWorkspace() {
 	WorkspaceLock = flock.New(filepath.Join(WorkspaceDir, ".lock"))
 	WorkspaceLock = flock.New(filepath.Join(WorkspaceDir, ".lock"))
-	if err := WorkspaceLock.Lock(); nil != err {
+	ok, err := WorkspaceLock.TryLock()
+	if ok {
+		return
+	}
+	if nil != err {
 		logging.LogErrorf("lock workspace [%s] failed: %s", WorkspaceDir, err)
 		logging.LogErrorf("lock workspace [%s] failed: %s", WorkspaceDir, err)
-		os.Exit(ExitCodeWorkspaceLocked)
+	} else {
+		logging.LogErrorf("lock workspace [%s] failed", WorkspaceDir)
 	}
 	}
+	os.Exit(ExitCodeWorkspaceLocked)
 }
 }
 
 
 func UnlockWorkspace() {
 func UnlockWorkspace() {