Skip to content

Commit

Permalink
Improve child process (#123)
Browse files Browse the repository at this point in the history
* Fix killing process

* Fix killing process

* Stopping persistent process and fix restarting process spawning twice

* Stopping persistent process and fix restarting process spawning twice

* Fix process being briefly restarted on quitting
  • Loading branch information
SRWieZ authored Nov 11, 2024
1 parent 502bfe5 commit 304c328
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 19 deletions.
2 changes: 2 additions & 0 deletions resources/js/electron-plugin/dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { electronApp, optimizer } from "@electron-toolkit/utils";
import { retrieveNativePHPConfig, retrievePhpIniSettings, runScheduler, startAPI, startPhpApp, startQueue, } from "./server";
import { notifyLaravel } from "./server/utils";
import { resolve } from "path";
import { stopAllProcesses } from "./server/api/childProcess";
import ps from "ps-node";
class NativePHP {
constructor() {
Expand Down Expand Up @@ -50,6 +51,7 @@ class NativePHP {
if (this.schedulerInterval) {
clearInterval(this.schedulerInterval);
}
stopAllProcesses();
this.killChildProcesses();
});
app.on("browser-window-created", (_, window) => {
Expand Down
41 changes: 35 additions & 6 deletions resources/js/electron-plugin/dist/server/api/childProcess.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import express from 'express';
import { utilityProcess } from 'electron';
import state from '../state';
import { notifyLaravel } from "../utils";
import { join } from 'path';
const router = express.Router();
const killSync = require('kill-sync');
function startProcess(settings) {
const { alias, cmd, cwd, env, persistent } = settings;
if (getProcess(alias) !== undefined) {
Expand Down Expand Up @@ -55,8 +65,10 @@ function startProcess(settings) {
code,
}
});
const settings = Object.assign({}, getSettings(alias));
delete state.processes[alias];
if (persistent) {
if (settings.persistent) {
console.log('Process [' + alias + '] wathchdog restarting...');
startProcess(settings);
}
});
Expand All @@ -71,8 +83,14 @@ function stopProcess(alias) {
if (proc === undefined) {
return;
}
if (proc.kill()) {
delete state.processes[alias];
state.processes[alias].settings.persistent = false;
console.log('Process [' + alias + '] stopping with PID [' + proc.pid + '].');
killSync(proc.pid, 'SIGTERM', true);
proc.kill();
}
export function stopAllProcesses() {
for (const alias in state.processes) {
stopProcess(alias);
}
}
function getProcess(alias) {
Expand All @@ -92,17 +110,28 @@ router.post('/stop', (req, res) => {
stopProcess(alias);
res.sendStatus(200);
});
router.post('/restart', (req, res) => {
router.post('/restart', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
const { alias } = req.body;
const settings = getSettings(alias);
const settings = Object.assign({}, getSettings(alias));
stopProcess(alias);
if (settings === undefined) {
res.sendStatus(410);
return;
}
const waitForProcessDeletion = (timeout, retry) => __awaiter(void 0, void 0, void 0, function* () {
const start = Date.now();
while (state.processes[alias] !== undefined) {
if (Date.now() - start > timeout) {
return;
}
yield new Promise(resolve => setTimeout(resolve, retry));
}
});
yield waitForProcessDeletion(5000, 100);
console.log('Process [' + alias + '] restarting...');
const proc = startProcess(settings);
res.json(proc);
});
}));
router.get('/get/:alias', (req, res) => {
const { alias } = req.params;
const proc = state.processes[alias];
Expand Down
6 changes: 5 additions & 1 deletion resources/js/electron-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from "./server";
import { notifyLaravel } from "./server/utils";
import { resolve } from "path";
import { stopAllProcesses } from "./server/api/childProcess";
import ps from "ps-node";

class NativePHP {
Expand Down Expand Up @@ -58,9 +59,12 @@ class NativePHP {

app.on("before-quit", () => {
if (this.schedulerInterval) {
clearInterval(this.schedulerInterval);
clearInterval(this.schedulerInterval);
}

// close all child processes from the app
stopAllProcesses();

this.killChildProcesses();
});

Expand Down
39 changes: 33 additions & 6 deletions resources/js/electron-plugin/src/server/api/childProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { notifyLaravel } from "../utils";
import { join } from 'path';

const router = express.Router();
const killSync = require('kill-sync');

function startProcess(settings) {
const {alias, cmd, cwd, env, persistent} = settings;
Expand Down Expand Up @@ -75,9 +76,12 @@ function startProcess(settings) {
}
});

const settings = {...getSettings(alias)};

delete state.processes[alias];

if (persistent) {
if (settings.persistent) {
console.log('Process [' + alias + '] wathchdog restarting...');
startProcess(settings);
}
});
Expand All @@ -96,8 +100,18 @@ function stopProcess(alias) {
return;
}

if (proc.kill()) {
delete state.processes[alias];
// Set persistent to false to prevent the process from restarting.
state.processes[alias].settings.persistent = false;

console.log('Process [' + alias + '] stopping with PID [' + proc.pid + '].');

killSync(proc.pid, 'SIGTERM', true); // Kill tree
proc.kill(); // Does not work but just in case. (do not put before killSync)
}

export function stopAllProcesses() {
for (const alias in state.processes) {
stopProcess(alias);
}
}

Expand All @@ -123,10 +137,10 @@ router.post('/stop', (req, res) => {
res.sendStatus(200);
});

router.post('/restart', (req, res) => {
router.post('/restart', async (req, res) => {
const {alias} = req.body;

const settings = getSettings(alias);
const settings = {...getSettings(alias)};

stopProcess(alias);

Expand All @@ -135,8 +149,21 @@ router.post('/restart', (req, res) => {
return;
}

const proc = startProcess(settings);
// Wait for the process to stop with a timeout of 5s
const waitForProcessDeletion = async (timeout, retry) => {
const start = Date.now();
while (state.processes[alias] !== undefined) {
if (Date.now() - start > timeout) {
return;
}
await new Promise(resolve => setTimeout(resolve, retry));
}
};

await waitForProcessDeletion(5000, 100);

console.log('Process [' + alias + '] restarting...');
const proc = startProcess(settings);
res.json(proc);
});

Expand Down
7 changes: 7 additions & 0 deletions resources/js/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions resources/js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"express": "^4.18.2",
"fs-extra": "^11.1.1",
"get-port": "^5.1.1",
"kill-sync": "^1.0.3",
"menubar": "^9.4.0",
"ps-node": "^0.1.6",
"tree-kill": "^1.2.2",
Expand Down
17 changes: 11 additions & 6 deletions resources/js/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1103,15 +1103,15 @@
minimatch "^3.0.4"
plist "^3.0.4"

"@esbuild/darwin-arm64@0.18.20":
"@esbuild/darwin-x64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz"
integrity sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==
resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz"
integrity sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==

"@esbuild/darwin-arm64@0.21.5":
"@esbuild/darwin-x64@0.21.5":
version "0.21.5"
resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz"
integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==
resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz"
integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==

"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
version "4.4.1"
Expand Down Expand Up @@ -4940,6 +4940,11 @@ keyv@^4.0.0, keyv@^4.5.3:
dependencies:
json-buffer "3.0.1"

kill-sync@^1.0.3:
version "1.0.3"
resolved "https://registry.npmjs.org/kill-sync/-/kill-sync-1.0.3.tgz"
integrity sha512-3UKwyIpWxg2WGrYyN3f+Fh68QZ4WApTHWwEnyeDK96HSRy9In9UQvanCwIsaLQV7gOzczotBeoX8jgPNZ1g2Zw==

kind-of@^6.0.2, kind-of@^6.0.3:
version "6.0.3"
resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz"
Expand Down

0 comments on commit 304c328

Please sign in to comment.