Skip to content

feature request: fork call and IPC #35

Open
@zh99998

Description

@zh99998

sometimes we want to execute elevated JavaScript script instead of external process.
if there is something like child_process.fork() call, it will be great.

documents about node.js native fork and ipc:

https://nodejs.org/api/child_process.html#child_process_child_process_fork_modulepath_args_options

note that spawn support IPC too, just specific it in stdio

https://nodejs.org/api/child_process.html#child_process_options_stdio

and in child process
https://nodejs.org/api/process.html#process_process_send_message_sendhandle_options_callback
https://nodejs.org/api/process.html#process_event_message

I've done something to simulate this ipc. it's ugly and not robust, but works for me.

it will break normal stdin/stdout since I'm using this to transfer messages. I don't know what does node.js native child_process ipc implement, maybe unixsock or named pipe?

here is my code:

import {remote} from "electron";

const Sudo = require('electron-sudo').default;

Sudo.prototype.fork = async function (modulePath, args, options) {
    let child = await this.spawn(remote.app.getPath('exe'), ['-e', modulePath].concat(args), options);
    readline.createInterface({input: child.stdout}).on('line', (line) => {
        child.emit('message', JSON.parse(line));
    });
    child.send = (message, sendHandle, options, callback)=> {
        child.stdin.write(JSON.stringify(message) + os.EOL);
        if (callback) {
            callback()
        }
    };
    return child
};

in index.js

function handleElevate() {
    if (process.argv[1] == '-e') {
        app.dock.hide();
        const os = require('os');
        const readline = require('readline');
        process.send = (message, sendHandle, options, callback)=> process.stdout.write(JSON.stringify(message) + os.EOL, callback);
        process.stdin.on('end', ()=> process.emit('disconnect'));
        readline.createInterface({input: process.stdin}).on('line', (line) => process.emit('message', JSON.parse(line)));
        require("./" + process.argv[2]);
        return true;
    }
}

if (handleElevate()) {
    return;
}

in my elevated module maotama.js, I'm using this to send raw-socket

const raw = require("raw-socket");
let socket = raw.createSocket({protocol: raw.Protocol.UDP});

let connect = (local_port, remote_port, remote_address)=> {
    let buffer = new Buffer(9);
    buffer.writeUInt16BE(local_port, 0);
    buffer.writeUInt16BE(remote_port, 2);
    buffer.writeUInt16BE(buffer.length, 4);
    socket.send(buffer, 0, buffer.length, remote_address, (error, bytes) => {
        if (error) {
            throw(error);
        }
    })
};

process.on('message', (message)=> {
    connect(...message.arguments);
});

process.on('disconnect', process.exit);

and calling

let child = await new Sudo({name: 'MyCard'}).fork('maotama')

child.send({
    action: 'connect',
    arguments: [app.network.port, port, address]
})

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions