I have two routes that is responsible to create and delete a child process: ( I must not create a child process before previous one is killed. only one child process at a time )
router.post('/run', controller.run) // create a child process
router.get('/kill', controller.kill) // delete that child process
in run controller I create child process. I tried both spawn and fork way.
using spawn methode:
run = async function (req, res, next) {
// using spawn
let spawn = require('child_process').spawn;
let p = spawn('node', [`${rootPath}/nodejs/grabRun.js`, req.body.modelI]);
p.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
p.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
p.stdin.on('error', (error) => console.log("error caught: ", error));
p.on('exit', (code) => {
console.log(`child process exited with code ${code}`); // this is alwayse called when killed
});
global.p = p
res.send("OK")
}
using fork methode:
run = async function (req, res, next) {
// using fork
const { fork } = require("child_process");
const p = fork(`${rootPath}/nodejs/grabRun.js`,[req.body.modelId]);
p.on("close", function (code) {
console.log("child process exited with code " + code); // this is alwayse called when killed
});
p.on("error", (err) => {
// This will be called with err being an AbortError if the controller aborts
console.log('p:',err);
});
global.p = p
res.send("OK")
}
I used global object in node to save child process. so I can destroy it in another api.
for kill controller:
killGrab = function (req, res) {
// p.send('exit');
let kill = global.p.kill('SIGKILL') // or SIGINT signal
console.log('kill',kill) // it returns true
global.controller = null
global.p = null
res.send("ok")
// spawn("taskkill", ["/pid", global.p.pid, '/f', '/t']);
// console.log('PId:',global.p.pid)
}
and script that I want run in child process:
// grabRun file
const testAddon = require('../build/Release/testaddon.node');
// process.on('SIGINT', () => {
// console.log('SIGINT signal received.')
// process.exit()
// })
//
// process.on('SIGKILL', () => {
// console.log('SIGINT signal received.')
// process.exit()
// })
process.on("message", function (message) {
console.log(`Message from main.js: ${message}`);
process.send("Nathan");
if (message==='exit')
process.exit()
});
console.log('GrabRun ..');
let modelId = Number(process.argv[2])
let data = {"model_index":[modelId]}
let r = testAddon.RunGrab({ji: JSON.stringify(data)});
console.log('GrabRun:', r);
Problem
first time I call /run route, it create child process and then call /kill route, it kill child process successfully.
but then I call /run I know runGrab file is executed because I see console result stdout: GrabRun ... but then close event is called immidiatly :
child process exited with code 3221226505 kill true
I also wnated to try process.exit() in child process but:
process.on('SIGINT', () => {}) // also SIGKILL is not called
is not executed.
Question
How can I generate and kill a child process dynamically like using API?
This is complete log from powershell. ( some socket.io socket message also exists in logs. I don't know why socket is closed when I kill child process)
PS F:\ArkaPro\glass\Halcon-1> npm run start
>> > test-addon@1.0.0 start
> node nodejs/server.js
net Server is listening on port 4661
Listening on port 3000
Socket on connection...
client connected: ui-H2buDFXwAhsnVAAAB
OPTIONS /api/run 204 0.453 ms - 0
POST /api/run 200 7.310 ms - 2
stdout: GrabRun ..
Number of concurrent connections to the server : 1
kill true
GET /api/kill 304 2.670 ms - -
Error : Error: read ECONNRESET
onClose Bytes read : 57
onClose Bytes written : 0
Socket closed!
true
Socket was closed coz of transmission error
undefined
socket: server namespace disconnect
child process exited with code null
OPTIONS /api/run 204 0.183 ms - 0
POST /api/run 200 8.477 ms - 2
stdout: GrabRun ..
child process exited with code 3221226505
kill false
GET /api/kill 304 1.216 ms - -
Terminate batch job (Y/N)? y
Thanks in advance.