I'm working on a project which requires me to spawn a pseudo-terminal (native addon) and then handle its file descriptor to my NodeJS code for some remote terminal stuff purposes. It works like a charm with node 0.10.x but it doesn't with 0.11.x nor 0.12.
Here's my C common code : (For readability purposes I removed all error checking but there's none, all syscalls work fine)
#define _XOPEN_SOURCE 600
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/select.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <signal.h>
static void handler_sigchld(int status) {
wait(&status);
printf("Child process died with status: %d\n", status);
}
static int get_pty(void) {
int fdm, fds;
fdm = posix_openpt(O_RDWR);
grantpt(fdm);
unlockpt(fdm);
fds = open(ptsname(fdm), O_RDWR);
signal(SIGCHLD, handler_sigchld);
if (fork() == 0) {
dup2(fds, 0);
dup2(fds, 1);
dup2(fds, 2);
setsid();
ioctl(0, TIOCSCTTY, 1);
{
char **child_av = (char**)malloc(sizeof(char*) * 2);
child_av[0] = (char*)"/bin/sh";
child_av[1] = (char*)NULL;
execv(child_av[0], child_av);
return (-1);
}
}
return (fdm);
}
Here's my node 0.10.32 C++ wrap :
#include <node.h>
#include <v8.h>
using namespace v8;
Handle<Value> OpenPty(const Arguments& args) {
HandleScope scope;
int fd_master = get_pty();
Local<Number> num = Number::New(fd_master);
return scope.Close(num);
}
void init(Handle<Object> exports) {
exports->Set(String::NewSymbol("posix_openpt"),
FunctionTemplate::New(OpenPty)->GetFunction());
}
NODE_MODULE(posix_openpt, init)
Node 0.11.14 C++ wrap :
#include <node.h>
using namespace v8;
void OpenPty(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
int fd_master = get_pty();
Local<Number> ret = Number::New(isolate, fd_master);
args.GetReturnValue().Set(ret);
}
void init(Handle<Object> exports) {
NODE_SET_METHOD(exports, "posix_openpt", OpenPty);
}
NODE_MODULE(posix_openpt, init)
Compilation via node-gyp also works fine for both node versions.
And finally here's my JS code :
var tty = require('tty');
var pty = require('./build/Release/posix_openpt.node');
var fd = pty.posix_openpt();
var term = new tty.ReadStream(fd);
console.log('FD: ' + fd);
term.write('ls -l\n');
term.pipe(process.stdout);
Result with node 0.10.32 (as expected we got output from our pseudo-terminal) :

Result with node 0.11.14 (we got nothing):

My stream doesn't respond to anything, I've also tried piping stdin into it.
Any thoughts on how and why node updates would affect this behaviour ?
Thanks.