Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Mysterious bug with tty.ReadStream since v0.11.x (0.12 as well) #8468

Closed
jshkurti opened this issue Sep 29, 2014 · 3 comments
Closed

Mysterious bug with tty.ReadStream since v0.11.x (0.12 as well) #8468

jshkurti opened this issue Sep 29, 2014 · 3 comments

Comments

@jshkurti
Copy link

Hello,

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) :
v10

Result with node 0.11.14 (we got nothing):
v11

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.

@Unitech
Copy link

Unitech commented Sep 30, 2014

Same error here with https://github.com/chjj/pty.js with Node 0.11.x and a zombie process appears

@trevnorris
Copy link

On the side, your v0.11 can be simplified to the following:

#include <node.h>

using namespace v8;

void OpenPty(const FunctionCallbackInfo<Value>& args) {
  args.GetReturnValue().Set(static_cast<uint32_t>(get_pty()));
}

void init(Handle<Object> exports) {
  NODE_SET_METHOD(exports, "posix_openpt", OpenPty);
}

NODE_MODULE(posix_openpt, init)

@jasnell
Copy link
Member

jasnell commented Jun 30, 2015

@jshkurti ... I know it's been a while, but is this still an issue for you? Have you tested with v0.12.5 or io.js?

@Trott Trott closed this as completed Apr 22, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants