fibjs/fibjs

"stdio: ['ipc']" not documented in fibjs website and child_process.send() works only in this 'ipc' case

forchid opened this issue · 1 comments

I try to build a application that has communication between parent-child processes by child_process module, Error: [20009] Invalid procedure call raised and this child process property connected is false when calling a child process send() method. In nodejs website, I see the 'ipc' stdio option, it works both fibjs and nodejs, but it not documented in fibjs website.

Test case

// multi-process-test.js
const child_process = require('child_process');
const net = require('net');
const path = require('path');
const fibjs = 'fibjs' === process.argv[0];

let co = null;
if (fibjs) co = require('coroutine');

const chPath = path.join(__dirname, 'so-child-process.js');
const cmd = co? 'fibjs': 'node';
// 1)child process connected false!
const child = child_process.spawn(cmd, [chPath], { stdio: 'pipe'/*default*/ });
// 2)child process connected false!
//const child = child_process.spawn(cmd, [chPath], { stdio: 'ignore' });
// 3)child process connected false!
//const child = child_process.spawn(cmd, [chPath], { stdio: 'inherit' });
// OK! But 'ipc' not documented in fibjs website!
//const child = child_process.spawn(cmd, [chPath], { stdio: ['ipc'] });

child.on('exit', exit);
if (co) {
	while(!child.connected) {
    	console.log('Parent: wait for parent-child pipe conn, current %s', 
        child.connected);
		try {
			child.send({ cmd: 'test' });
		} catch (e) {
			console.log('Parent: send() failed when child not connected - ' + e);
		}
    	co.sleep(1000);
	}
	console.log('Parent: connected to child? %s', child.connected);
	console.log('Parent: >> start');
	child.send({ cmd: 'start' });
} else {
	let timer = setInterval(() => {
		if (!child.connected) {
			console.log('Parent: wait for parent-child pipe conn, current %s', 
        		child.connected);
		} else {
			console.log('Parent: connected to child? %s', child.connected);
			console.log('Parent: >> start');
			child.send({ cmd: 'start' });
			clearInterval(timer);
		}
	}, 1000);
}

child.on('message', m => {
    console.log('Parent: << %s', m.msg);
    switch (m.msg) {
        case 'Ok':
            ping();
            break;
		case 'Pong':
			console.log('Parent: >> exit');
			child.send({ cmd: 'exit' });
			break;
        case 'Bye':
            break;
        default:
            break;
    }
});

function exit() {
    if (fibjs) child.join();
    console.log('Parent: child exit code %s', child.exitCode);
    console.log('Parent: parent also exit');
    process.exit(0);
}

function ping() {
	console.log('Parent: >> ping');
    child.send({ cmd: 'ping' });
}

// so-child-process.js
const fibjs = 'fibjs' == process.argv[0];
let co = null;
if (fibjs) co = require('coroutine');

process.on('message', (m) => {
    console.log('soc: << %s', JSON.stringify(m));
    switch (m.cmd) {
        case 'start':
		    process.send({ msg: 'child starting ..' });
		    init();
            break;
        case 'ping':
		    process.send({ msg: 'Pong' });
            break;
        case 'exit':
            process.send({ msg: 'Bye' });
            process.exit(0);
        default:
            process.send(m);
            break;
    }
});

function init() {
    process.send({ msg: 'Ok' });
}

if (fibjs) {
	do {
        console.log('Child: wait for parent-child pipe conn, current %s', 
            process.connected);
        co.sleep(1000);
	} while (!process.connected);
} else {
	let timer = setInterval(() => {
		if (!process.connected) {
			console.log('Child: wait for parent-child pipe conn, current %s', 
            process.connected);
		} else {
			clearInterval(timer);
		}
	}, 1000);
}
>fibjs multi-process-test.js
Parent: wait for parent-child pipe conn, current false
Parent: send() failed when child not connected - Error: [20009] Invalid procedure call.
Parent: wait for parent-child pipe conn, current false
Parent: send() failed when child not connected - Error: [20009] Invalid procedure call.
Parent: wait for parent-child pipe conn, current false
Parent: send() failed when child not connected - Error: [20009] Invalid procedure call.
Parent: wait for parent-child pipe conn, current false
Parent: send() failed when child not connected - Error: [20009] Invalid procedure call.

ipc channels are only supported in child processes of child_process.fork, just modify this line:

const child = child_process.fork([chPath]);