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()
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
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
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 _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
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