def maybe_handle_stdin(want):
   if want:
     with NailgunStreamStdinReader.open(maybe_shutdown_socket, stdin_isatty) as fd:
       yield fd
   else:
     with open('/dev/null', 'rb') as fh:
       yield fh.fileno()
Exemple #2
0
    def _pipe_stdio(self, sock, stdin_isatty, stdout_isatty, stderr_isatty):
        """Handles stdio redirection in the case of pipes and/or mixed pipes and ttys."""
        stdio_writers = ((ChunkType.STDOUT, stdout_isatty), (ChunkType.STDERR,
                                                             stderr_isatty))
        types, ttys = zip(*(stdio_writers))
        with NailgunStreamStdinReader.open(sock, stdin_isatty) as stdin_fd,\
             NailgunStreamWriter.open_multi(sock, types, ttys) as ((stdout_fd, stderr_fd), writer),\
             stdio_as(stdout_fd=stdout_fd, stderr_fd=stderr_fd, stdin_fd=stdin_fd):
            # N.B. This will be passed to and called by the `DaemonExiter` prior to sending an
            # exit chunk, to avoid any socket shutdown vs write races.
            stdout, stderr = sys.stdout, sys.stderr

            def finalizer():
                try:
                    stdout.flush()
                    stderr.flush()
                finally:
                    time.sleep(
                        .001
                    )  # HACK: Sleep 1ms in the main thread to free the GIL.
                    writer.stop()
                    writer.join()
                    stdout.close()
                    stderr.close()

            yield finalizer
Exemple #3
0
    def _nailgunned_stdio(self, sock):
        """Redirects stdio to the connected socket speaking the nailgun protocol."""
        # Determine output tty capabilities from the environment.
        stdin_isatty, stdout_isatty, stderr_isatty = NailgunProtocol.isatty_from_env(
            self._env)

        # Launch a thread to read stdin data from the socket (the only messages expected from the client
        # for the remainder of the protocol), and threads to copy from stdout/stderr pipes onto the
        # socket.
        with NailgunStreamWriter.open_multi(
               sock,
               (ChunkType.STDOUT, ChunkType.STDERR),
               None,
               (stdout_isatty, stderr_isatty)
             ) as ((stdout_fd, stderr_fd), writer),\
             NailgunStreamStdinReader.open(sock, stdin_isatty) as stdin_fd,\
             stdio_as(stdout_fd=stdout_fd, stderr_fd=stderr_fd, stdin_fd=stdin_fd):
            # N.B. This will be passed to and called by the `DaemonExiter` prior to sending an
            # exit chunk, to avoid any socket shutdown vs write races.
            stdout, stderr = sys.stdout, sys.stderr

            def finalizer():
                try:
                    stdout.flush()
                    stderr.flush()
                finally:
                    time.sleep(
                        .001
                    )  # HACK: Sleep 1ms in the main thread to free the GIL.
                    writer.stop()
                    writer.join()
                    stdout.close()
                    stderr.close()

            yield finalizer
Exemple #4
0
 def maybe_handle_stdin(want):
     if want:
         # TODO: Launching this thread pre-fork to handle @rule input currently results
         # in an unhandled SIGILL in `src/python/pants/engine/scheduler.py, line 313 in pre_fork`.
         # More work to be done here in https://github.com/pantsbuild/pants/issues/6005
         with NailgunStreamStdinReader.open(sock, stdin_isatty) as fd:
             yield fd
     else:
         with open('/dev/null', 'rb') as fh:
             yield fh.fileno()
 def maybe_handle_stdin(want):
   if want:
     # TODO: Launching this thread pre-fork to handle @rule input currently results
     # in an unhandled SIGILL in `src/python/pants/engine/scheduler.py, line 313 in pre_fork`.
     # More work to be done here in https://github.com/pantsbuild/pants/issues/6005
     with NailgunStreamStdinReader.open(sock, stdin_isatty) as fd:
       yield fd
   else:
     with open('/dev/null', 'rb') as fh:
       yield fh.fileno()
Exemple #6
0
    def _nailgunned_stdio(self, sock):
        """Redirects stdio to the connected socket speaking the nailgun protocol."""
        # Determine output tty capabilities from the environment.
        stdin_isatty, stdout_isatty, stderr_isatty = NailgunProtocol.isatty_from_env(
            self._env)

        # If all stdio is a tty, there's only one logical I/O device (the tty device). This happens to
        # be addressable as a file in OSX and Linux, so we take advantage of that and directly open the
        # character device for output redirection - eliminating the need to directly marshall any
        # interactive stdio back/forth across the socket and permitting full, correct tty control with
        # no middle-man.
        if all((stdin_isatty, stdout_isatty, stderr_isatty)):
            stdin_ttyname, stdout_ttyname, stderr_ttyname = NailgunProtocol.ttynames_from_env(
                self._env)
            assert stdin_ttyname == stdout_ttyname == stderr_ttyname, (
                'expected all stdio ttys to be the same, but instead got: {}\n'
                'please file a bug at http://github.com/pantsbuild/pants'.
                format([stdin_ttyname, stdout_ttyname, stderr_ttyname]))
            with open(stdin_ttyname, 'rb+wb', 0) as tty:
                tty_fileno = tty.fileno()
                with stdio_as(stdin_fd=tty_fileno,
                              stdout_fd=tty_fileno,
                              stderr_fd=tty_fileno):

                    def finalizer():
                        termios.tcdrain(tty_fileno)

                    yield finalizer
        else:
            stdio_writers = ((ChunkType.STDOUT, stdout_isatty),
                             (ChunkType.STDERR, stderr_isatty))
            types, ttys = zip(*(stdio_writers))
            with NailgunStreamStdinReader.open(sock, stdin_isatty) as stdin_fd,\
                 NailgunStreamWriter.open_multi(sock, types, ttys) as ((stdout_fd, stderr_fd), writer),\
                 stdio_as(stdout_fd=stdout_fd, stderr_fd=stderr_fd, stdin_fd=stdin_fd):
                # N.B. This will be passed to and called by the `DaemonExiter` prior to sending an
                # exit chunk, to avoid any socket shutdown vs write races.
                stdout, stderr = sys.stdout, sys.stderr

                def finalizer():
                    try:
                        stdout.flush()
                        stderr.flush()
                    finally:
                        time.sleep(
                            .001
                        )  # HACK: Sleep 1ms in the main thread to free the GIL.
                        writer.stop()
                        writer.join()
                        stdout.close()
                        stderr.close()

                yield finalizer
Exemple #7
0
    def _nailgunned_stdio(self, sock):
        """Redirects stdio to the connected socket speaking the nailgun protocol."""
        # Determine output tty capabilities from the environment.
        stdin_isatty, stdout_isatty, stderr_isatty = NailgunProtocol.isatty_from_env(
            self._env)

        # Launch a thread to read stdin data from the socket (the only messages expected from the client
        # for the remainder of the protocol), and threads to copy from stdout/stderr pipes onto the
        # socket.
        with NailgunStreamStdinReader.open(sock, isatty=stdin_isatty) as stdin,\
             NailgunStreamWriter.open(sock, ChunkType.STDOUT, None, isatty=stdout_isatty) as stdout,\
             NailgunStreamWriter.open(sock, ChunkType.STDERR, None, isatty=stderr_isatty) as stderr:
            with stdio_as(stdout=stdout, stderr=stderr, stdin=stdin):
                yield
 def _pipe_stdio(self, sock, stdin_isatty, stdout_isatty, stderr_isatty):
   """Handles stdio redirection in the case of pipes and/or mixed pipes and ttys."""
   stdio_writers = (
     (ChunkType.STDOUT, stdout_isatty),
     (ChunkType.STDERR, stderr_isatty)
   )
   types, ttys = zip(*(stdio_writers))
   with NailgunStreamStdinReader.open(sock, stdin_isatty) as stdin_fd,\
        NailgunStreamWriter.open_multi(sock, types, ttys) as ((stdout_fd, stderr_fd), writer),\
        stdio_as(stdout_fd=stdout_fd, stderr_fd=stderr_fd, stdin_fd=stdin_fd):
     # N.B. This will be passed to and called by the `DaemonExiter` prior to sending an
     # exit chunk, to avoid any socket shutdown vs write races.
     stdout, stderr = sys.stdout, sys.stderr
     def finalizer():
       try:
         stdout.flush()
         stderr.flush()
       finally:
         time.sleep(.001)  # HACK: Sleep 1ms in the main thread to free the GIL.
         writer.stop()
         writer.join()
         stdout.close()
         stderr.close()
     yield finalizer