Skip to content

Instantly share code, notes, and snippets.

@pyhedgehog
Last active September 30, 2015 14:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pyhedgehog/e157c756d56c5b554451 to your computer and use it in GitHub Desktop.
Save pyhedgehog/e157c756d56c5b554451 to your computer and use it in GitHub Desktop.
Child pipe proof-of-concept

Pros:

  1. (against stdin/stdout usage) Leaves stdin for request data, stdout for response and stderr for logging.
  2. Uses standard Node child_process.spawn options.stdio[3]='ipc' technique.

Cons:

  1. Right now uses '\n' as separator - it's original flaw of Node 'ipc' implementation.
  2. Unportable: Node 'ipc' uses different implementation for different OSes. I.e. on Windows it uses named pipes and I've failed to fix child.py to work on windows. I can't ever imagine what it will be on Mac.
  3. Incompatible: Node 'ipc' can send handle via this socket. I had not yet found how it's implemented.
#!node
if(!process.send) {
console.log("Not started with accessible parent IPC.");
process.exit(1);
}
process.on('message', function(json) {
console.log('parent->child message passed', json);
process.send({type:'got', payload:json});
if(json.type === 'exit') process.exit(0);
});
#!/usr/bin/env python
import os
import sys
import socket
import pprint
import json
#pprint.pprint(dict(os.environ))
#print 'NODE_CHANNEL_FD =', os.environ.get('NODE_CHANNEL_FD')
fd = int(os.environ['NODE_CHANNEL_FD'])
if sys.platform == 'win32':
apiin = os.fdopen(fd, 'r')
apiout = os.fdopen(fd+1, 'w')
else:
api = socket.fromfd(fd, socket.AF_UNIX, socket.SOCK_STREAM)
apiin = api.makefile('r')
apiout = api.makefile('w')
while True:
data = apiin.readline()
data = json.loads(data)
print 'parent->child message passed', data
apiout.write(json.dumps({"type":"got", "payload":data})+'\n')
apiout.flush()
if data.get("type") == "exit":
break
#!node
var util = require('util');
var spawn = require('child_process').spawn;
//console.log(process.argv);
var action = process.argv[2]||'py';
//console.log('action =', action);
var child;
if(action === 'py') {
var proc = 'python';
var args = ['child.py'];
if(process.platform == 'win32') {
proc = 'py';
args = ['-2', 'child.py'];
//args = ['-3', 'child.py'];
}
//console.log(proc, args);
child = spawn(proc, args, {stdio:[0, 1, 2, 'ipc']});
} else if(action === 'js') {
child = spawn(process.execPath, ['child.js'], {stdio:[0, 1, 2, 'ipc']});
} else if(action === 'pfiles') {
child = spawn(action, [process.pid], {stdio:[0, 1, 2, 'ipc']});
} else if(action === 'pfiles1') {
child = spawn('sh', ['-c', 'exec pfiles $$'], {stdio:[0, 1, 2, 'ipc']});
} else {
child = spawn(action, [], {stdio:[0, 1, 2, 'ipc']});
}
//child.stdout.on('data', function (data) {
// console.log('stdout: ' + data);
//});
//child.stderr.on('data', function (data) {
// console.log('stderr: ' + data);
//});
child.on('close', function (code) {
console.log('child process exited with code ' + code);
});
child.on('error', function (err) {
console.log('child process not started with error ' + err);
});
child.on('message', function(json) {
console.log('child->parent message passed', json);
});
//console.log('child', child);
//console.log('child.stdio', child.stdio);
child.send({type:'intro'});
setTimeout(function() {
child.send({type:'exit'});
}, 1500);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment