Ejemplo n.º 1
0
 def _signal_int(self, signum, frame):
     """Signal handler for SIGINT - Ctrl+C may have been pressed."""
     self.send_signal(signal.CTRL_C_EVENT if xp.ON_WINDOWS else signum)
     if self.proc is not None and self.proc.poll() is not None:
         self._restore_sigint(frame=frame)
     if xt.on_main_thread() and not xp.ON_WINDOWS:
         signal.pthread_kill(threading.get_ident(), signal.SIGINT)
Ejemplo n.º 2
0
 def _restore_sigquit(self, frame=None):
     old = self.old_quit_handler
     if old is not None:
         if xt.on_main_thread():
             signal.signal(signal.SIGQUIT, old)
         self.old_quit_handler = None
     if frame is not None:
         self._disable_cbreak_stdin()
Ejemplo n.º 3
0
 def _restore_sigtstp(self, frame=None):
     old = self.old_tstp_handler
     if old is not None:
         if xt.on_main_thread():
             signal.signal(signal.SIGTSTP, old)
         self.old_tstp_handler = None
     if frame is not None:
         self._disable_cbreak_stdin()
     self._restore_suspend_keybind()
Ejemplo n.º 4
0
 def _restore_sigint(self, frame=None):
     old = self.old_int_handler
     if old is not None:
         if xt.on_main_thread():
             signal.signal(signal.SIGINT, old)
         self.old_int_handler = None
     if frame is not None:
         self._disable_cbreak_stdin()
         if old is not None and old is not self._signal_int:
             old(signal.SIGINT, frame)
Ejemplo n.º 5
0
 def _restore_sigint(self, frame=None):
     old = self.old_int_handler
     if old is not None:
         if xt.on_main_thread():
             signal.signal(signal.SIGINT, old)
         self.old_int_handler = None
     if frame is not None:
         if old is not None and old is not self._signal_int:
             old(signal.SIGINT, frame)
     if self._interrupted:
         self.returncode = 1
Ejemplo n.º 6
0
 def wait(self, timeout=None):
     """Dispatches to Popen.wait(), but also does process cleanup such as
     joining this thread and replacing the original window size signal
     handler.
     """
     self._disable_cbreak_stdin()
     rtn = self.proc.wait(timeout=timeout)
     self.join()
     # need to replace the old signal handlers somewhere...
     if self.old_winch_handler is not None and xt.on_main_thread():
         signal.signal(signal.SIGWINCH, self.old_winch_handler)
         self.old_winch_handler = None
     self._clean_up()
     return rtn
Ejemplo n.º 7
0
 def _signal_int(self, signum, frame):
     """Signal handler for SIGINT - Ctrl+C may have been pressed."""
     # Check if we have already been interrupted. This should prevent
     # the possibility of infinite recursion.
     if self._interrupted:
         return
     self._interrupted = True
     # close file handles here to stop an processes piped to us.
     handles = (
         self.p2cread,
         self.p2cwrite,
         self.c2pread,
         self.c2pwrite,
         self.errread,
         self.errwrite,
     )
     for handle in handles:
         safe_fdclose(handle)
     if self.poll() is not None:
         self._restore_sigint(frame=frame)
     if xt.on_main_thread() and not xp.ON_WINDOWS:
         signal.pthread_kill(threading.get_ident(), signal.SIGINT)
Ejemplo n.º 8
0
    def __init__(
        self,
        f,
        args,
        stdin=None,
        stdout=None,
        stderr=None,
        universal_newlines=False,
        close_fds=False,
        env=None,
    ):
        """Parameters
        ----------
        f : function
            The function to be executed.
        args : list
            A (possibly empty) list containing the arguments that were given on
            the command line
        stdin : file-like, optional
            A file-like object representing stdin (input can be read from
            here).  If `stdin` is not provided or if it is explicitly set to
            `None`, then an instance of `io.StringIO` representing an empty
            file is used.
        stdout : file-like, optional
            A file-like object representing stdout (normal output can be
            written here).  If `stdout` is not provided or if it is explicitly
            set to `None`, then `sys.stdout` is used.
        stderr : file-like, optional
            A file-like object representing stderr (error output can be
            written here).  If `stderr` is not provided or if it is explicitly
            set to `None`, then `sys.stderr` is used.
        universal_newlines : bool, optional
            Whether or not to use universal newlines.
        close_fds : bool, optional
            Whether or not to close file descriptors. This is here for Popen
            compatability and currently does nothing.
        env : Mapping, optional
            Environment mapping.
        """
        self.orig_f = f
        self.f = partial_proxy(f)
        self.args = args
        self.pid = None
        self.returncode = None
        self._closed_handle_cache = {}

        handles = self._get_handles(stdin, stdout, stderr)
        (
            self.p2cread,
            self.p2cwrite,
            self.c2pread,
            self.c2pwrite,
            self.errread,
            self.errwrite,
        ) = handles

        # default values
        self.stdin = stdin
        self.stdout = stdout
        self.stderr = stderr
        self.close_fds = close_fds
        self.env = env or builtins.__xonsh__.env
        self._interrupted = False

        if xp.ON_WINDOWS:
            if self.p2cwrite != -1:
                self.p2cwrite = xli.msvcrt.open_osfhandle(
                    self.p2cwrite.Detach(), 0)
            if self.c2pread != -1:
                self.c2pread = xli.msvcrt.open_osfhandle(
                    self.c2pread.Detach(), 0)
            if self.errread != -1:
                self.errread = xli.msvcrt.open_osfhandle(
                    self.errread.Detach(), 0)

        if self.p2cwrite != -1:
            self.stdin = io.open(self.p2cwrite, "wb", -1)
            if universal_newlines:
                self.stdin = io.TextIOWrapper(self.stdin,
                                              write_through=True,
                                              line_buffering=False)
        elif isinstance(stdin, int) and stdin != 0:
            self.stdin = io.open(stdin, "wb", -1)

        if self.c2pread != -1:
            self.stdout = io.open(self.c2pread, "rb", -1)
            if universal_newlines:
                self.stdout = io.TextIOWrapper(self.stdout)

        if self.errread != -1:
            self.stderr = io.open(self.errread, "rb", -1)
            if universal_newlines:
                self.stderr = io.TextIOWrapper(self.stderr)

        # Set some signal handles, if we can. Must come before process
        # is started to prevent deadlock on windows
        self.old_int_handler = None
        if xt.on_main_thread():
            self.old_int_handler = signal.signal(signal.SIGINT,
                                                 self._signal_int)
        # start up the proc
        super().__init__()
        self.start()
Ejemplo n.º 9
0
    def __init__(self, *args, stdin=None, stdout=None, stderr=None, **kwargs):
        super().__init__()

        self.daemon = True

        self.lock = threading.RLock()
        env = XSH.env
        # stdin setup
        self.orig_stdin = stdin
        if stdin is None:
            self.stdin_fd = 0
        elif isinstance(stdin, int):
            self.stdin_fd = stdin
        else:
            self.stdin_fd = stdin.fileno()
        self.store_stdin = env.get("XONSH_STORE_STDIN")
        self.timeout = env.get("XONSH_PROC_FREQUENCY")
        self.in_alt_mode = False
        self.stdin_mode = None
        self._tc_cc_vsusp = b"\x1a"  # default is usually ^Z
        self._disable_suspend_keybind()
        # stdout setup
        self.orig_stdout = stdout
        self.stdout_fd = 1 if stdout is None else stdout.fileno()
        self._set_pty_size()
        # stderr setup
        self.orig_stderr = stderr
        # Set some signal handles, if we can. Must come before process
        # is started to prevent deadlock on windows
        self.proc = None  # has to be here for closure for handles
        self.old_int_handler = self.old_winch_handler = None
        self.old_tstp_handler = self.old_quit_handler = None
        if xt.on_main_thread():
            self.old_int_handler = signal.signal(signal.SIGINT,
                                                 self._signal_int)
            if xp.ON_POSIX:
                self.old_tstp_handler = signal.signal(signal.SIGTSTP,
                                                      self._signal_tstp)
                self.old_quit_handler = signal.signal(signal.SIGQUIT,
                                                      self._signal_quit)
            if xp.CAN_RESIZE_WINDOW:
                self.old_winch_handler = signal.signal(signal.SIGWINCH,
                                                       self._signal_winch)
        # start up process
        if xp.ON_WINDOWS and stdout is not None:
            os.set_inheritable(stdout.fileno(), False)

        try:
            self.proc = proc = subprocess.Popen(*args,
                                                stdin=stdin,
                                                stdout=stdout,
                                                stderr=stderr,
                                                **kwargs)
        except Exception:
            self._clean_up()
            raise

        self.pid = proc.pid
        self.universal_newlines = uninew = proc.universal_newlines
        if uninew:
            self.encoding = enc = env.get("XONSH_ENCODING")
            self.encoding_errors = err = env.get("XONSH_ENCODING_ERRORS")
            self.stdin = io.BytesIO()  # stdin is always bytes!
            self.stdout = io.TextIOWrapper(io.BytesIO(),
                                           encoding=enc,
                                           errors=err)
            self.stderr = io.TextIOWrapper(io.BytesIO(),
                                           encoding=enc,
                                           errors=err)
        else:
            self.encoding = self.encoding_errors = None
            self.stdin = io.BytesIO()
            self.stdout = io.BytesIO()
            self.stderr = io.BytesIO()
        self.suspended = False
        self.prevs_are_closed = False
        # This is so the thread will use the same swapped values as the origin one.
        self.original_swapped_values = XSH.env.get_swapped_values()
        self.start()