def become_tty_fg(self,child=True):
     os.setpgrp()
     hdlr = signal.signal(signal.SIGTTOU, signal.SIG_IGN)
     tty = os.open('/dev/tty', os.O_RDWR)
     os.tcsetpgrp(tty, os.getpgrp())
     if child:
         signal.signal(signal.SIGTTOU, hdlr)
Example #2
0
 def _give_terminal_to(pgid):
     st = _shell_tty()
     if st is not None and os.isatty(st):
         oldmask = signal.pthread_sigmask(signal.SIG_BLOCK,
                                          _block_when_giving)
         os.tcsetpgrp(st, pgid)
         signal.pthread_sigmask(signal.SIG_SETMASK, oldmask)
Example #3
0
 def _give_terminal_to(pgid):
     st = _shell_tty()
     if st is not None and os.isatty(st):
         oldmask = signal.pthread_sigmask(signal.SIG_BLOCK,
                                          _block_when_giving)
         os.tcsetpgrp(st, pgid)
         signal.pthread_sigmask(signal.SIG_SETMASK, oldmask)
Example #4
0
def run_and_kill_children_on_exit(fn: "typing.Callable[[], typing.Any]"):
    error = False
    try:
        opgrp = os.getpgrp()
        if opgrp != os.getpid():
            # Create new process group and become its leader
            os.setpgrp()
            # Preserve whether our process group is the terminal leader
            with suppress_sigttou():
                tty = None
                try:
                    tty = os.open('/dev/tty', os.O_RDWR)
                except OSError:
                    pass
                if tty is not None and os.tcgetpgrp(tty) == opgrp:
                    os.tcsetpgrp(tty, os.getpgrp())
                    os.close(tty)
        fn()
    except KeyboardInterrupt:
        error = True
        sys.exit("Exiting due to Ctrl+C")
    except subprocess.CalledProcessError as err:
        error = True
        extra_msg = (". Working directory was ", err.cwd) if hasattr(err, "cwd") else ()
        if err.stderr is not None:
            extra_msg += ("\nStandard error was:\n", err.stderr.decode("utf-8"))
        fatal_error("Command ", "`" + commandline_to_str(err.cmd) + "` failed with non-zero exit code ",
                    err.returncode, *extra_msg, fatal_when_pretending=True, sep="", exit_code=err.returncode)
    finally:
        if error:
            signal.signal(signal.SIGTERM, signal.SIG_IGN)
            os.killpg(0, signal.SIGTERM)  # Tell all child processes to exit
Example #5
0
 async def _run():
     self.fg_proc = proc = await astart_command(cmd,
                                                stdin=None,
                                                stdout=None,
                                                stderr=None,
                                                **kw)
     await proc.communicate()
     self.fg_proc = None
     # One of the main use cases for this function is to run interactive
     # bash in a subshell. Interactive bash of course creates a process
     # group for itself and sets it as the foreground process group for
     # the controlling terminal. Usually on exit, our process group
     # becomes the foreground process group again but when the subshell
     # is killed for some reason it does not. This causes the tcsetattr
     # that screen.start() does to either cause SIGTTOU to be sent, or
     # if that is ignored (either because there is no shell around to do
     # job control things or we are ignoring it) fail with EIO. So we
     # force our process group back into the foreground with this
     # call. That's not quite enough though because tcsetpgrp *also*
     # causes SIGTTOU to be sent to a background process that calls it,
     # but fortunately if we ignore that (done in start_urwid below),
     # the call still succeeds.
     #
     # I would now like a drink.
     os.tcsetpgrp(0, os.getpgrp())
     screen.start()
     if after_hook is not None:
         after_hook()
Example #6
0
def set_foreground(pgid):
    """
    Use to be called by a the a shell to give
    the foreground to any pgid, including himself.
    """
    with open("/dev/tty") as control_term:
        os.tcsetpgrp(control_term.fileno(), pgid)
Example #7
0
 def give_terminal_to(pgid):
     if pgid is None:
         return False
     oldmask = _pthread_sigmask(signal.SIG_BLOCK, _block_when_giving)
     try:
         os.tcsetpgrp(FD_STDERR, pgid)
         return True
     except ProcessLookupError:
         # when the process finished before giving terminal to it,
         # see issue #2288
         return False
     except OSError as e:
         if e.errno == 22:  # [Errno 22] Invalid argument
             # there are cases that all the processes of pgid have
             # finished, then we don't need to do anything here, see
             # issue #2220
             return False
         elif e.errno == 25:  # [Errno 25] Inappropriate ioctl for device
             # There are also cases where we are not connected to a
             # real TTY, even though we may be run in interactive
             # mode. See issue #2267 for an example with emacs
             return False
         else:
             raise
     finally:
         _pthread_sigmask(signal.SIG_SETMASK, oldmask)
Example #8
0
 def give_terminal_to(pgid):
     if pgid is None:
         return False
     oldmask = _pthread_sigmask(signal.SIG_BLOCK, _block_when_giving)
     try:
         os.tcsetpgrp(FD_STDERR, pgid)
         return True
     except ProcessLookupError:
         # when the process finished before giving terminal to it,
         # see issue #2288
         return False
     except OSError as e:
         if e.errno == 22:  # [Errno 22] Invalid argument
             # there are cases that all the processes of pgid have
             # finished, then we don't need to do anything here, see
             # issue #2220
             return False
         elif e.errno == 25:  # [Errno 25] Inappropriate ioctl for device
             # There are also cases where we are not connected to a
             # real TTY, even though we may be run in interactive
             # mode. See issue #2267 for an example with emacs
             return False
         else:
             raise
     finally:
         _pthread_sigmask(signal.SIG_SETMASK, oldmask)
Example #9
0
 def become_tty_fg():
     # make child process use the fg
     # http://stackoverflow.com/questions/15200700/how-do-i-set-the-terminal-foreground-process-group-for-a-process-im-running-und
     os.setpgrp()
     hdlr = signal.signal(signal.SIGTTOU, signal.SIG_IGN)
     tty = os.open('/dev/tty', os.O_RDWR)
     os.tcsetpgrp(tty, os.getpgrp())
     signal.signal(signal.SIGTTOU, hdlr)
Example #10
0
 def _give_terminal_to(pgid):
     # over-simplified version of:
     #    give_terminal_to from bash 4.3 source, jobs.c, line 4030
     # this will give the terminal to the process group pgid
     if _shell_tty is not None and os.isatty(_shell_tty):
         oldmask = signal.pthread_sigmask(signal.SIG_BLOCK, _block_when_giving)
         os.tcsetpgrp(_shell_tty, pgid)
         signal.pthread_sigmask(signal.SIG_SETMASK, oldmask)
Example #11
0
File: jobs.py Project: selepo/xonsh
 def _give_terminal_to(pgid):
     # over-simplified version of:
     #    give_terminal_to from bash 4.3 source, jobs.c, line 4030
     # this will give the terminal to the process group pgid
     if _shell_tty is not None and os.isatty(_shell_tty):
         oldmask = signal.pthread_sigmask(signal.SIG_BLOCK, _block_when_giving)
         os.tcsetpgrp(_shell_tty, pgid)
         signal.pthread_sigmask(signal.SIG_SETMASK, oldmask)
Example #12
0
def run_command_in_interactive_shell(command, shell):
    try:
        subprocess.call([shell, '-i', '-c', command])
    finally:
        # The terminal was attached to the interactive shell we just
        # started, and left in limbo when that shell terminated. Retrieve
        # it for this process group, so that we can still print and recieve
        # keypresses.
        os.tcsetpgrp(0, os.getpgrp())
Example #13
0
 def restore_pgrp() -> None:
     old_handler = signal.getsignal(signal.SIGTTOU)
     signal.signal(signal.SIGTTOU, signal.SIG_IGN)
     try:
         # This will raise SIGTTOU if we're not in the
         # foreground process group, which we have to ignore
         os.tcsetpgrp(their_fd, os.getpgrp())
     finally:
         signal.signal(signal.SIGTTOU, old_handler)
 def _leave_foreground(self):
     """
     This resets the foreground process group.
     :return:
     """
     if self.is_foreground:
         os.tcsetpgrp(self.controlling_terminal, self.orig_fore_pg)
         os.close(self.controlling_terminal)
         self.is_foreground = False
Example #15
0
def run_command_in_interactive_shell(command, shell):
    try:
        subprocess.call([shell, '-i', '-c', command])
    finally:
        # The terminal was attached to the interactive shell we just
        # started, and left in limbo when that shell terminated. Retrieve
        # it for this process group, so that we can still print and recieve
        # keypresses.
        os.tcsetpgrp(0, os.getpgrp())
Example #16
0
def tcsetpgrp(space, fd, pgid):
    """ tcsetpgrp(fd, pgid)

    Set the process group associated with the terminal given by a fd.
    """
    try:
        os.tcsetpgrp(fd, pgid)
    except OSError as e:
        raise wrap_oserror(space, e)
Example #17
0
def tcsetpgrp(space, fd, pgid):
    """ tcsetpgrp(fd, pgid)

    Set the process group associated with the terminal given by a fd.
    """
    try:
        os.tcsetpgrp(fd, pgid)
    except OSError as e:
        raise wrap_oserror(space, e)
Example #18
0
 def _controlTerminal(self):
     try:
         # the child should control stdin -- if stdin is a tty
         # that can be controlled
         if sys.stdin.isatty():
             os.tcsetpgrp(0, os.getpgrp())
     except AttributeError:
         # stdin might not even have an isatty method
         pass
Example #19
0
 def _controlTerminal(self):
     try:
         # the child should control stdin -- if stdin is a tty
         # that can be controlled
         if sys.stdin.isatty():
             os.tcsetpgrp(0, os.getpgrp())
     except AttributeError:
        # stdin might not even have an isatty method
         pass
Example #20
0
def run_command_full(command):
    if os.name == 'nt':
        p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    elif os.name == 'posix':
        # Run the command supporting .bashrc
        subprocess.call([os.getenv('SHELL'), '-i', '-c', command], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        # Retrieve the terminal
        os.tcsetpgrp(0,os.getpgrp())
    out, err = p.communicate()
    return out, err
Example #21
0
def set_as_tty_foreground():
    # Create a new process group just for us
    os.setpgrp()
    # Becoming terminal foreground sends SIGTTOU which normally kills the
    # process. Ignore SIGTTOU.
    signal.signal(signal.SIGTTOU, signal.SIG_IGN)
    # Prepare a terminal device
    tty = os.open('/dev/tty', os.O_RDWR)
    # Become terminal foreground
    os.tcsetpgrp(tty, os.getpgrp())
Example #22
0
def become_fg_process():
    """
    Executed in the child process to assume control over the terminal
    """
    os.setpgrp()
    ttou_handler = signal.signal(signal.SIGTTOU, signal.SIG_IGN)
    tty = os.open('/dev/tty', os.O_RDWR)
    os.tcsetpgrp(tty, os.getpgrp())
    os.close(tty)
    signal.signal(signal.SIGTTOU, ttou_handler)
Example #23
0
def become_fg_process_group():
    # we are going to get SIGTTOU because terminal settings change, which would put us to sleep
    hdlr = signal.signal(signal.SIGTTOU, signal.SIG_IGN)
    os.setpgrp(
    )  # create a new process group so the newly started process can get ctrl-c,z
    tty = os.open('/dev/tty', os.O_RDWR)
    os.tcsetpgrp(tty,
                 os.getpgrp())  # make the process group foreground for the tty
    os.close(tty)
    signal.signal(signal.SIGTTOU, hdlr)  # restore normal signal handling
Example #24
0
 def __init__(self, pid=None, jobs=None, leaderCurrent=None):
     if pid is None:
         pid = os.getpid()
         os.setpgid(os.getpid(), os.getpid())
         os.tcsetpgrp(1, os.getpid())
     self.pere = pid
     if jobs is None:
         jobs = Jobs()
     self.jobs = jobs
     self.leaderCurrent = leaderCurrent
Example #25
0
def execWithRedirect(command, argv, stdin = 0, stdout = 1, stderr = 2,
                searchPath = 0, root = '/', newPgrp = 0, ignoreTermSigs = 0):
    stdin = getfd(stdin)
    if stdout == stderr:
        stdout = getfd(stdout)
        stderr = stdout
    else:
        stdout = getfd(stdout)
        stderr = getfd(stderr)

    childpid = os.fork()
    if (not childpid):
        if (root and root != '/'):
            os.chroot(root)
            os.chdir("/")

        if ignoreTermSigs:
            signal.signal(signal.SIGTSTP, signal.SIG_IGN)
            signal.signal(signal.SIGINT, signal.SIG_IGN)

        if type(stdin) == type("a"):
            stdin = os.open(stdin, os.O_RDONLY)
        if type(stdout) == type("a"):
            stdout = os.open(stdout, os.O_RDWR)
        if type(stderr) == type("a"):
            stderr = os.open(stderr, os.O_RDWR)

        if stdin != 0:
            os.dup2(stdin, 0)
            os.close(stdin)
        if stdout != 1:
            os.dup2(stdout, 1)
            if stdout != stderr:
                os.close(stdout)
        if stderr != 2:
            os.dup2(stderr, 2)
            os.close(stderr)

        if (searchPath):
            os.execvp(command, argv)
        else:
            os.execv(command, argv)

        sys.exit(1)

    if newPgrp:
        os.setpgid(childpid, childpid)
        oldPgrp = os.tcgetpgrp(0)
        os.tcsetpgrp(0, childpid)

    status = -1
    try:
        (pid, status) = os.waitpid(childpid, 0)
    except OSError, (errno, msg):
        print __name__, "waitpid:", msg
Example #26
0
def fg(num=0):
    global jobS, chld
    pid = os.fork()
    if pid == 0:
        os.tcsetpgrp(1, os.getpgid(os.getpid()))
    else:
        chld = pid
        jobS[num] = [chld, "running"]
        os.setpgid(pid, 0)
        os.kill(jobS[num][0], signal.SIGCONT)
        signal.pause()
Example #27
0
def become_tty_fg():
    """Become foreground tty.

    This is used before spawning the subprocess so key sequences are correctly passed down.
    We also use it to grab it back when sleeping.
    """
    os.setpgrp()
    hdlr = signal.signal(signal.SIGTTOU, signal.SIG_IGN)
    tty = os.open('/dev/tty', os.O_RDWR)
    os.tcsetpgrp(tty, os.getpgrp())
    signal.signal(signal.SIGTTOU, hdlr)
    os.close(tty)
Example #28
0
def preexec_fn():
    # Block SIGTTOU generated by the tcsetpgrp call
    orig_mask = signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGTTOU])

    # Put us in a new process group.
    os.setpgid(0, 0)

    # And put it in the foreground.
    fd = os.open("/dev/tty", os.O_RDONLY)
    os.tcsetpgrp(fd, os.getpgid(0))
    os.close(fd)

    signal.pthread_sigmask(signal.SIG_SETMASK, orig_mask)
Example #29
0
    def close(self):
        """ Reassert control of tty.  Closing stdin, stderr, and and stdout
            will get rid of the last pointer to the slave fd of the pseudo
            tty, which should cause the logging process to stop.  We wait
            for it to die before continuing
        """
        if not self.logging:
            return
        self.closed = True
        # restore old terminal settings before quitting
        if self.oldStdin != 0:
            os.dup2(self.oldStdin, 0)
        os.dup2(self.oldStdout, 1)
        os.dup2(self.oldStderr, 2)
        if self.oldTermios is not None:
            termios.tcsetattr(0, termios.TCSADRAIN, self.oldTermios)
        if self.oldStdin != 0:
            os.close(self.oldStdin)
        os.close(self.oldStdout)
        os.close(self.oldStderr)
        try:
            # control stdin -- if stdin is a tty
            # that can be controlled
            if sys.stdin.isatty() and self.restoreTerminalControl:
                os.tcsetpgrp(0, os.getpgrp())
        except AttributeError:
            # stdin might not even have an isatty method
            pass

        # Wait for child logging process to die.  Send successively ruder
        # signals if it does not do so within a reasonable time.  The primary
        # reason that it would not die immediately is that a process has forked
        # while holding the TTY file descriptor, and thus the logger is still
        # polling it for output.
        signals = [signal.SIGTERM, signal.SIGKILL]
        while signals:
            start = time.time()
            while time.time() - start < 10:
                pid, status = os.waitpid(self.loggerPid, os.WNOHANG)
                if pid:
                    break
                time.sleep(0.1)
            else:
                # Child process did not die.
                signum = signals.pop(0)
                os.kill(self.loggerPid, signum)
                continue
            break
        else:
            # Last signal was a KILL, so wait indefinitely.
            os.waitpid(self.loggerPid, 0)
Example #30
0
    def close(self):
        """ Reassert control of tty.  Closing stdin, stderr, and and stdout
            will get rid of the last pointer to the slave fd of the pseudo
            tty, which should cause the logging process to stop.  We wait
            for it to die before continuing
        """
        if not self.logging:
            return
        self.closed = True
        # restore old terminal settings before quitting
        if self.oldStdin != 0:
            os.dup2(self.oldStdin, 0)
        os.dup2(self.oldStdout, 1)
        os.dup2(self.oldStderr, 2)
        if self.oldTermios is not None:
            termios.tcsetattr(0, termios.TCSADRAIN, self.oldTermios)
        if self.oldStdin != 0:
            os.close(self.oldStdin)
        os.close(self.oldStdout)
        os.close(self.oldStderr)
        try:
            # control stdin -- if stdin is a tty
            # that can be controlled
            if sys.stdin.isatty() and self.restoreTerminalControl:
                os.tcsetpgrp(0, os.getpgrp())
        except AttributeError:
            # stdin might not even have an isatty method
            pass

        # Wait for child logging process to die.  Send successively ruder
        # signals if it does not do so within a reasonable time.  The primary
        # reason that it would not die immediately is that a process has forked
        # while holding the TTY file descriptor, and thus the logger is still
        # polling it for output.
        signals = [signal.SIGTERM, signal.SIGKILL]
        while signals:
            start = time.time()
            while time.time() - start < 10:
                pid, status = os.waitpid(self.loggerPid, os.WNOHANG)
                if pid:
                    break
                time.sleep(0.1)
            else:
                # Child process did not die.
                signum = signals.pop(0)
                os.kill(self.loggerPid, signum)
                continue
            break
        else:
            # Last signal was a KILL, so wait indefinitely.
            os.waitpid(self.loggerPid, 0)
Example #31
0
 def fg(self, numero_job):
     if numero_job == []:
         fils = [job.pid for job in self.jobs.jobs]
         pidfils = fils[-1]
         pgid = os.getpgid(pidfils)
         os.tcsetpgrp(1, pgid)
         fgpid = pgid
         os.kill(-pgid, signal.SIGCONT)
         pid, status = os.waitpid(pidfils, os.WUNTRACED)
         if os.WIFSTOPPED(status):
             print("Fg stopped")
         elif os.WTERMSIG(status):
             self.jobs.removebyPId(pid)
             print("Fg Process killed")
         else:
             self.jobs.removebyPId(pidfils)
         os.tcsetpgrp(1, self.pere)
     else:
         fils = [job.pid for job in self.jobs.jobs]
         pidfils = fils[numero_job[0] - 1]
         pgid = os.getpgid(pidfils)
         os.tcsetpgrp(1, pgid)
         fgpid = pgid
         os.kill(-pgid, signal.SIGCONT)
         pid, status = os.waitpid(pidfils, os.WUNTRACED)
         if os.WIFSTOPPED(status):
             print("Fg stopped")
         elif os.WTERMSIG(status):
             self.jobs.removebyPId(pid)
             print("Fg Process killed")
         else:
             self.jobs.removebyPId(pidfils)
         os.tcsetpgrp(1, self.pere)
Example #32
0
def _safe_tcsetpgrp(fd, pgrp):
    """Set |pgrp| as the controller of the tty |fd|."""
    try:
        curr_pgrp = os.tcgetpgrp(fd)
    except OSError as e:
        # This can come up when the fd is not connected to a terminal.
        if e.errno == errno.ENOTTY:
            return
        raise

    # We can change the owner only if currently own it.  Otherwise we'll get
    # stopped by the kernel with SIGTTOU and that'll hit the whole group.
    if curr_pgrp == os.getpgrp():
        os.tcsetpgrp(fd, pgrp)
Example #33
0
def _safe_tcsetpgrp(fd, pgrp):
    """Set |pgrp| as the controller of the tty |fd|."""
    try:
        curr_pgrp = os.tcgetpgrp(fd)
    except OSError as e:
        # This can come up when the fd is not connected to a terminal.
        if e.errno == errno.ENOTTY:
            return
        raise

    # We can change the owner only if currently own it.  Otherwise we'll get
    # stopped by the kernel with SIGTTOU and that'll hit the whole group.
    if curr_pgrp == os.getpgrp():
        os.tcsetpgrp(fd, pgrp)
Example #34
0
def _new_tty_foreground_process_group():
    try:
        os.setpgrp()
    except Exception as e:
        warning_message("Failed to call os.setpgrp()", e)
        raise e
    with suppress_sigttou():
        try:
            with scoped_open('/dev/tty', os.O_RDWR, ignore_open_error=True) as tty:
                if tty is not None:
                    os.tcsetpgrp(tty, os.getpgrp())
        except Exception as e:
            warning_message("Failed to call os.tcsetpgrp()", e)
            raise e
Example #35
0
 def run_test_in_separate_process(file_descriptor_stdin, result_queue):
     """Change process group, run test and return result via a queue."""
     orig_pgid = os.getpgrp()
     os.setpgrp()
     result_queue.put("pgrp")
     if not quiet:
         sys.stdin = os.fdopen(file_descriptor_stdin)
     result = test.run()
     result_queue.put(result)
     if not quiet:
         try:
             os.tcsetpgrp(file_descriptor_stdin, orig_pgid)
         except OSError as error:
             if error.args[0] == 25:
                 pass
 def _maybe_become_foreground(self):
     """
     Become the foreground process if the user requested it and it is
     possible. Allows the "Parent" process (aka this one) to get
     SIGINT (Ctrl+C). Useful if running in your terminal or from python repl.
     :return:
     """
     if self._should_become_foreground():
         hdlr = signal.signal(signal.SIGTTOU, signal.SIG_IGN)  # ignore since would cause this process to stop
         self.controlling_terminal = os.open(os.ctermid(), os.O_RDWR)
         self.orig_fore_pg = os.tcgetpgrp(self.controlling_terminal)  # sends SIGTTOU to this process
         os.tcsetpgrp(self.controlling_terminal, self.childpid)
         signal.signal(signal.SIGTTOU, hdlr)
         return True
     return False
Example #37
0
 def give_terminal_to(pgid):
     oldmask = signal.pthread_sigmask(signal.SIG_BLOCK,
                                      _block_when_giving)
     try:
         os.tcsetpgrp(FD_STDERR, pgid)
         return True
     except OSError as e:
         if e.errno == 22:  # [Errno 22] Invalid argument
             # there are cases that all the processes of pgid have
             # finished, then we don't need to do anything here, see
             # issue #2220
             return False
         else:
             raise
     finally:
         signal.pthread_sigmask(signal.SIG_SETMASK, oldmask)
Example #38
0
    def _preExec(self):
        # Set process group
        logging.debug("CHILD: setpgid(0, 0)")
        os.setpgid(0, 0)
        if self.jobCtrl.foreground:
            logging.debug("CHILD: tcsetpgrp(0, %d)", os.getpgrp())
            os.tcsetpgrp(0, os.getpgrp())

        # Restore signal to default values
        signal.signal(signal.SIGINT, signal.SIG_DFL)
        signal.signal(signal.SIGTERM, signal.SIG_DFL)
        signal.signal(signal.SIGTTOU, signal.SIG_DFL)
        signal.signal(signal.SIGTTIN, signal.SIG_DFL)
        signal.signal(signal.SIGTSTP, signal.SIG_DFL)
        signal.signal(signal.SIGCHLD, signal.SIG_DFL)
        signal.signal(signal.SIGCONT, signal.SIG_DFL)
Example #39
0
    def _preExec(self):
        # Set process group
        logging.debug("CHILD: setpgid(0, 0)")
        os.setpgid(0, 0)
        if self.jobCtrl.foreground:
            logging.debug("CHILD: tcsetpgrp(0, %d)", os.getpgrp())
            os.tcsetpgrp(0, os.getpgrp())

        # Restore signal to default values
        signal.signal(signal.SIGINT, signal.SIG_DFL)
        signal.signal(signal.SIGTERM, signal.SIG_DFL)
        signal.signal(signal.SIGTTOU, signal.SIG_DFL)
        signal.signal(signal.SIGTTIN, signal.SIG_DFL)
        signal.signal(signal.SIGTSTP, signal.SIG_DFL)
        signal.signal(signal.SIGCHLD, signal.SIG_DFL)
        signal.signal(signal.SIGCONT, signal.SIG_DFL)
Example #40
0
def become_tty_fg():
    """Force a subprocess call to become the foreground process.

    A helper function for subprocess.call(preexec_fn=) that makes the
    called command to become the foreground process in the terminal,
    allowing the user to interact with that process.

    Control is returned to this script after the called process has
    terminated.
    """
    #From: http://stackoverflow.com/questions/15200700/how-do-i-set-the-terminal-foreground-process-group-for-a-process-im-running-und

    os.setpgrp()
    hdlr = signal.signal(signal.SIGTTOU, signal.SIG_IGN)
    tty = os.open('/dev/tty', os.O_RDWR)
    os.tcsetpgrp(tty, os.getpgrp())
    signal.signal(signal.SIGTTOU, hdlr)
Example #41
0
def become_tty_fg():
    """Force a subprocess call to become the foreground process.

    A helper function for subprocess.call(preexec_fn=) that makes the
    called command to become the foreground process in the terminal,
    allowing the user to interact with that process.

    Control is returned to this script after the called process has
    terminated.
    """
    #From: http://stackoverflow.com/questions/15200700/how-do-i-set-the-terminal-foreground-process-group-for-a-process-im-running-und

    os.setpgrp()
    hdlr = signal.signal(signal.SIGTTOU, signal.SIG_IGN)
    tty = os.open('/dev/tty', os.O_RDWR)
    os.tcsetpgrp(tty, os.getpgrp())
    signal.signal(signal.SIGTTOU, hdlr)
Example #42
0
def give_terminal_to(pgid):
    signals = {
        signal.SIGTTOU,
        signal.SIGTTIN,
        signal.SIGTSTP,
        signal.SIGCHLD,
    }

    old_mask = signal.pthread_sigmask(signal.SIG_BLOCK, signals)
    try:
        os.tcsetpgrp(2, pgid)
        return True
    except ProcessLookupError:
        return False
    except OSError:
        return False
    finally:
        signal.pthread_sigmask(signal.SIG_SETMASK, old_mask)
Example #43
0
 def exec1(self, arguments):
     pid = os.fork()
     if pid == 0:
         os.setpgid(0, 0)
         os.tcsetpgrp(1, os.getpid())
         signal.signal(signal.SIGTSTP, signal.SIG_DFL)
         self.redirect(arguments[0])
     os.setpgid(pid, pid)
     os.tcsetpgrp(0, pid)
     self.jobs.addJobs(
         processus(pid=pid,
                   state='Foreground',
                   name=" ".join(arguments[0][1])))
     self.jobs.setJobID()
     pid, status = os.waitpid(pid, os.WUNTRACED)
     if os.WIFSTOPPED(status):
         temp = [job for job in self.jobs.jobs if job.state == "Foreground"]
         if temp != []:
             temp[0].changeState("Suspended")
             print("Stoped by ctrl z")
     elif os.WTERMSIG(status):
         self.jobs.removebyPId(pid)
         print("Process killed")
     else:
         self.jobs.removebyPId(pid)
         print("Exited normally")
     os.tcsetpgrp(1, self.pere)
Example #44
0
    def signalHandler(self, signo, _frame):
        logging.debug("signalHandler: signo=%d", signo)
        if signo == signal.SIGINT or signo == signal.SIGTERM:
            self.job.kill()

        elif signo == signal.SIGCHLD:
            # Get status of child
            try:
                (pid, status) = os.waitpid(
                    self.job.pid, os.WNOHANG + os.WCONTINUED + os.WUNTRACED)
            except OSError as ex:
                # Simulate success in case of error (very rare case...)
                logging.debug("waitpid: %s", str(ex))
                pid = self.job.pid
                status = 512
            logging.debug("waitpid: pid=%d status=%s", pid, status)
            self.job.updateStatus(status)

            if self.job.stopped:
                # If sub-process was associated with console, change it to us
                if os.tcgetpgrp(0) == self.job.pgid:
                    logging.debug("tcsetpgrp(0, %d)", os.getpgrp())
                    os.tcsetpgrp(0, os.getpgrp())
                # Propagate the stop to our process group
                logging.debug("killpg(0, SIGSTOP)")
                os.killpg(0, signal.SIGSTOP)

        elif signo == signal.SIGCONT:
            # If we are associated with console, change it to sub-process
            self.tcpgrp = os.tcgetpgrp(0)
            self.foreground = (self.tcpgrp == os.getpgrp())
            logging.debug("tcpgrp=%d foreground=%d", self.tcpgrp,
                          self.foreground)
            if self.foreground:
                logging.debug("tcsetpgrp(0, %d)", self.job.pgid)
                os.tcsetpgrp(0, self.job.pgid)
            # Propagate continue to sub-process
            logging.debug("killpg(%d, SIGCONT)", self.job.pgid)
            os.killpg(self.job.pgid, signal.SIGCONT)
def forkExecCapture(instr):
  childpid=0;
  sys.stdout.flush()
  sys.stdin.flush()
  sys.stderr.flush()
  prev=signal.signal(signal.SIGTTOU, signal.SIG_IGN)
  os.tcsetpgrp(sys.stdin.fileno(),os.getpid())
  try:
    ( child_pid, fd ) = pty.fork()    # OK
    #~ child_pid, fd = os.forkpty()      # OK
  except OSError as e:
    print str(e)

  if child_pid == 0:
    #~ os.tcsetpgrp(fd, tcgrp) # note: fd=-1 for child!
    # note: in child process, every print is redirected to parent!
    #
    #childpid=os.getpid()
    if FDBG: print "In Child Process: PID# %s" % os.getpid()
    # no need for REP=gdb.execute("n",True,to_string=True)
    # here we capture everything anyways; just run
    gdb.execute(instr)
    time.sleep(0.5)
    print RET
    if FDBG: return "child returns"
    #else: return 0
  else:
    #~ os.tcsetpgrp(fd, tcgrp) # Inappropriate ioctl for device
    os.tcsetpgrp(sys.stdin.fileno(),os.getpid())
    if FDBG: print "In Parent Process: PID# %s" % os.getpid()
    # now must 'drain' the printout from child process
    #~ os.waitpid(os.getpid(), 0) # No child processes
    time.sleep(0.5)
    CHILDREPLY=os.read(fd, 10000)
    time.sleep(0.5)
    # wait for child to exit
    if FDBG: print CHILDREPLY
    if FDBG: return "parent returns"
    else: return CHILDREPLY
Example #46
0
    def signalHandler(self, signo, _frame):
        logging.debug("signalHandler: signo=%d", signo)
        if signo == signal.SIGINT or signo == signal.SIGTERM:
            self.job.kill()

        elif signo == signal.SIGCHLD:
            # Get status of child
            try:
                (pid, status) = os.waitpid(self.job.pid,
                        os.WNOHANG + os.WCONTINUED + os.WUNTRACED)
            except OSError as ex:
                # Simulate success in case of error (very rare case...)
                logging.debug("waitpid: %s", str(ex))
                pid = self.job.pid
                status = 512
            logging.debug("waitpid: pid=%d status=%s", pid, status)
            self.job.updateStatus(status)

            if self.job.stopped:
                # If sub-process was associated with console, change it to us
                if os.tcgetpgrp(0) == self.job.pgid:
                    logging.debug("tcsetpgrp(0, %d)", os.getpgrp())
                    os.tcsetpgrp(0, os.getpgrp())
                # Propagate the stop to our process group
                logging.debug("killpg(0, SIGSTOP)")
                os.killpg(0, signal.SIGSTOP)

        elif signo == signal.SIGCONT:
            # If we are associated with console, change it to sub-process
            self.tcpgrp = os.tcgetpgrp(0)
            self.foreground = (self.tcpgrp == os.getpgrp())
            logging.debug("tcpgrp=%d foreground=%d", self.tcpgrp, self.foreground)
            if self.foreground:
                logging.debug("tcsetpgrp(0, %d)", self.job.pgid)
                os.tcsetpgrp(0, self.job.pgid)
            # Propagate continue to sub-process
            logging.debug("killpg(%d, SIGCONT)", self.job.pgid)
            os.killpg(self.job.pgid, signal.SIGCONT)
Example #47
0
        sys.exit(1)

    if newPgrp:
        os.setpgid(childpid, childpid)
        oldPgrp = os.tcgetpgrp(0)
        os.tcsetpgrp(0, childpid)

    status = -1
    try:
        (pid, status) = os.waitpid(childpid, 0)
    except OSError, (errno, msg):
        print __name__, "waitpid:", msg

    if newPgrp:
        os.tcsetpgrp(0, oldPgrp)

    return status

## Run an external program and capture standard out.
# @param command The command to run.
# @param argv A list of arguments.
# @param stdin The file descriptor to read stdin from.
# @param stderr The file descriptor to redirect stderr to.
# @param root The directory to chroot to before running command.
# @return The output of command from stdout.
def execWithCapture(command, argv, stdin = 0, stderr = 2, root='/'):
    def chroot():
        os.chroot(root)

    argv = list(argv)
Example #48
0
def main():
    # Setup logging
    setupLog()

    makeProg = os.environ.get("MAKE", "make")

    # Put in an environment variable the command line so we can find it
    os.environ["ALCHEMAKE_CMDLINE"] = " ".join([makeProg] + sys.argv[1:])

    # If not on a terminal, do NOT use job control, simply execute make...
    if not os.isatty(0):
        logging.warning("Not using job control")
        process = subprocess.Popen([makeProg] + sys.argv[1:], shell=False)
        process.wait()
        sys.exit(process.returncode)
        return

    # Create our job control object
    jobCtrl = JobCtrl()

    # Try to exit silently in case of interrupts...
    signal.signal(signal.SIGINT, jobCtrl.signalHandler)
    signal.signal(signal.SIGTERM, jobCtrl.signalHandler)

    # Job control
    signal.signal(signal.SIGTTOU, signal.SIG_IGN)
    signal.signal(signal.SIGTTIN, signal.SIG_IGN)
    signal.signal(signal.SIGTSTP, signal.SIG_IGN)
    signal.signal(signal.SIGCHLD, jobCtrl.signalHandler)
    signal.signal(signal.SIGCONT, jobCtrl.signalHandler)

    # Only redirect stderr (redirecting stdout causes issues if a child process
    # wants to use the terminal, like ncurses)
    # Force locale to have english messages that we will try to detect
    env = os.environ
    env["LANG"] = "C"
    cmdline = makeProg
    for arg in sys.argv[1:]:
        cmdline += " " + arg
    jobCtrl.job.launch(cmdline, stderr=subprocess.PIPE, env=env)

    # Read from stderr redirected in a pipe
    # only catch top level makefile errors (sub-make files error will eventually
    # generate a top level error)
    reError1 = re.compile(r"make: \*\*\* No rule to make target .*")
    reError2 = re.compile(r"make: \*\*\* \[[^\[\]]*\] Error [0-9]+")
    errorDetected = False
    while True:
        try:
            # Empty line means EOF detected, so exit loop
            line = jobCtrl.job.process.stderr.readline()
            if len(line) == 0:
                logging.debug("EOF detected")
                break
            if not errorDetected:
                sys.stderr.write(line)
            # Check for make error
            if reError1.match(line) or reError2.match(line):
                logging.debug("error detected")
                errorDetected = True
                jobCtrl.job.kill()
        except IOError:
            # Will occur when interrupted during read, an EOF will be read next
            pass

    # Only print message once at the end
    if errorDetected:
        sys.stderr.write("\n\033[31mMAKE ERROR DETECTED\n\033[00m")

    # Wait for sub-process to terminate
    logging.debug("wait sub-process")
    jobCtrl.job.process.wait()

    # Restore stuff
    if jobCtrl.tcpgrp != os.tcgetpgrp(0):
        try:
            logging.debug("tcsetpgrp(0, %d)", jobCtrl.tcpgrp)
            os.tcsetpgrp(0, jobCtrl.tcpgrp)
        except OSError:
            # Seems to occurs when launched in background and initial foreground
            # process is not there anymore, just ignore
            pass

    # Exit with same result as sub-process
    logging.debug("exit(%d)", jobCtrl.job.process.returncode)
    sys.exit(jobCtrl.job.process.returncode)
Example #49
0
File: run.py Project: nkhuyu/dtags
def main():
    global tmp_file, current_process, child_processes

    # https://stackoverflow.com/questions/25099895/
    signal.signal(signal.SIGTTOU, signal.SIG_IGN)

    # Ensure that child processes are cleaned up
    signal.signal(signal.SIGINT, kill_signal_handler)
    signal.signal(signal.SIGTERM, kill_signal_handler)
    atexit.register(cleanup_resources)

    tag_to_paths = load_tags()
    parser = argparse.ArgumentParser(
        prog='run',
        description=cmd_description,
        usage='run [options] [targets] command',
        formatter_class=HelpFormatter
    )
    parser.add_argument(
        '-p', '--parallel',
        help='run the command in parallel',
        action='store_true'
    )
    parser.add_argument(
        '-e', '--exit-codes',
        help='display the exit codes',
        action='store_true'
    )
    parser.add_argument(
        'arguments',
        type=str,
        nargs=argparse.REMAINDER,
        metavar='[targets]',
        help='tags or paths to run the command for'
    ).completer = ChoicesCompleter(tag_to_paths.keys())
    autocomplete(parser)
    parsed = parser.parse_args()

    # Separate the targets from the command
    index = 0
    targets = OrderedDict()
    while index < len(parsed.arguments):
        target = parsed.arguments[index]
        if target in tag_to_paths:
            for path in sorted(tag_to_paths[target].keys()):
                targets[path] = target
            index += 1
        elif target.startswith('@'):
            parser.error('unknown tag {}'.format(target))
        elif os.path.isdir(target):
            path = expand_path(target)
            if path not in targets:
                targets[path] = None
            index += 1
        else:
            break  # beginning of the command

    # Join the command arguments into a string
    command_arguments = parsed.arguments[index:]
    if len(command_arguments) == 0:
        command = None
    elif len(command_arguments) == 1:
        command = ' '.join(command_arguments)
    else:
        command = ' '.join(
            "'{}'".format(arg) if ' ' in arg else arg
            for arg in command_arguments
        )
    if not (targets and command):
        parser.error('too few arguments')

    if parsed.parallel:
        # Run the command in parallel
        for path, tag in targets.items():
            tmp_file = tempfile.TemporaryFile(mode='w+t')
            current_process = subprocess.Popen(
                '{} -i -c "{}"'.format(shell, command),
                cwd=path,
                shell=True,
                stdout=tmp_file,
                stderr=tmp_file,
                preexec_fn=os.setsid,
            )
            child_processes.append((path, tag, current_process, tmp_file))
        for path, tag, current_process, tmp_file in child_processes:
            exit_code = current_process.wait()
            tail = ' ({}{}{})'.format(PINK, tag, CLEAR) if tag else ':'
            print('{}>>> {}{}{}{}'.format(
                YELLOW, CYAN, path, tail, CLEAR
            ))
            tmp_file.seek(0)
            lines = tmp_file.readlines()
            offset = 0
            if len(lines) > 0 and contains_ctrl_error_msg(lines[0]):
                offset += 1
            if len(lines) > 1 and contains_ctrl_error_msg(lines[1]):
                offset += 1
            sys.stdout.write(''.join(lines[offset:]))
            tmp_file.close()
            if parsed.exit_codes:
                print('{}>>> {}exit code: {}{}'.format(
                    YELLOW, RED, exit_code, CLEAR
                ))
            sys.stdout.write('\n')
    else:
        # Run the command sequentially
        full_command = []
        for path, tag in targets.items():
            tag_info = ' ({}{}{})'.format(PINK, tag, CLEAR) if tag else ':'
            if parsed.exit_codes:
                tail = 'printf "{}>>> {}exit code: $?{}\n\n"'.format(
                    YELLOW, RED, CLEAR
                )
            else:
                tail = 'printf "\n"'
            full_command.append(
                '(printf "{header}"; cd {path} && {cmd};{tail})'.format(
                    header='{}>>> {}{}{}{}\n'.format(
                        YELLOW, CYAN, path, CLEAR, tag_info
                    ),
                    path=path,
                    cmd=command,
                    tail=tail
                )
            )
        subprocess.call(
            [shell, '-i', '-c', '{}'.format(';'.join(full_command))],
            stderr=sys.stdout.fileno()
        )
        # https://stackoverflow.com/questions/25099895/
        os.tcsetpgrp(0, os.getpgrp())
    sys.exit(0)
Example #50
0
def execWithRedirect(command, argv, stdin = 0, stdout = 1, stderr = 2,	
		     searchPath = 0, root = '/', newPgrp = 0,
		     ignoreTermSigs = 0, closeFds = False):
    stdin = getfd(stdin)
    if stdout == stderr:
	stdout = getfd(stdout)
	stderr = stdout
    else:
	stdout = getfd(stdout)
	stderr = getfd(stderr)

#
# XXX What is this good for? If we can't run a command we'll error
#     out below won't we?
#
#    if not os.access (root + command, os.X_OK):
#	raise RuntimeError, command + " can not be run"

    childpid = os.fork()
    if (not childpid):
        if (root and root != '/'): 
	    os.chroot (root)
	    os.chdir("/")

	if ignoreTermSigs:
	    signal.signal(signal.SIGTSTP, signal.SIG_IGN)
	    signal.signal(signal.SIGINT, signal.SIG_IGN)

        if closeFds:
            try:
                os.closerange(3, os.sysconf("SC_OPEN_MAX"))
            except:
                pass

	if type(stdin) == type("a"):
	    stdin = os.open(stdin, os.O_RDONLY)
	if type(stdout) == type("a"):
	    stdout = os.open(stdout, os.O_RDWR)
	if type(stderr) == type("a"):
	    stderr = os.open(stderr, os.O_RDWR)

	if stdin != 0:
	    os.dup2(stdin, 0)
	    os.close(stdin)
	if stdout != 1:
	    os.dup2(stdout, 1)
	    if stdout != stderr:
		os.close(stdout)
	if stderr != 2:
	    os.dup2(stderr, 2)
	    os.close(stderr)

	if (searchPath):
	    os.execvp(command, argv)
	else:
	    os.execv(command, argv)

	sys.exit(1)

    if newPgrp:
	os.setpgid(childpid, childpid)
	oldPgrp = os.tcgetpgrp(0)
	os.tcsetpgrp(0, childpid)

    status = -1
    try:
        (pid, status) = os.waitpid(childpid, 0)
    except OSError as e:
        print "%s waitpid: %s" % (__name__, e.strerror)

    if newPgrp:
	os.tcsetpgrp(0, oldPgrp)

    return status
Example #51
0
    def run(self, quiet=False):
        """Run all tests in the defined suite of modules."""
        tests = self.tests()
        failedfast = False
        result_list = []

        for test in tests:
            if quiet:
                hijacked_stdout = sys.stdout
                hijacked_stderr = sys.stderr
                sys.stdout = open(path.join(self.settings['engine_folder'], ".hitch", "test.out"), "ab", 0)
                sys.stderr = open(path.join(self.settings['engine_folder'], ".hitch", "test.err"), "ab", 0)

            def run_test_in_separate_process(file_descriptor_stdin, result_queue):
                """Change process group, run test and return result via a queue."""
                orig_pgid = os.getpgrp()
                os.setpgrp()
                result_queue.put("pgrp")
                if not quiet:
                    sys.stdin = os.fdopen(file_descriptor_stdin)
                result = test.run()
                result_queue.put(result)
                if not quiet:
                    try:
                        os.tcsetpgrp(file_descriptor_stdin, orig_pgid)
                    except OSError as error:
                        if error.args[0] == 25:
                            pass

            if not quiet:
                try:
                    orig_stdin_termios = termios.tcgetattr(sys.stdin.fileno())
                except termios.error:
                    orig_stdin_termios = None
                orig_stdin_fileno = sys.stdin.fileno()
            orig_pgid = os.getpgrp()

            file_descriptor_stdin = sys.stdin.fileno()
            result_queue = multiprocessing.Queue()


            # Start new process to run test in, to isolate it from future test runs
            test_process = multiprocessing.Process(
                target=run_test_in_separate_process,
                args=(file_descriptor_stdin, result_queue)
            )

            test_timed_out = False

            test_process.start()

            # Ignore all exit signals but pass them on
            signal_pass_on_to_separate_process_group(test_process.pid)

            # Wait until PGRP is changed
            result_queue.get()

            # Make stdin go to the test process so that you can use ipython, etc.
            if not quiet:
                try:
                    os.tcsetpgrp(file_descriptor_stdin, os.getpgid(test_process.pid))
                except OSError as error:
                    if error.args[0] == 25:
                        pass

            # Wait until process has finished
            proc = psutil.Process(test_process.pid)
            test_timeout = self.settings.get("test_timeout", None)
            test_shutdown_timeout = self.settings.get("test_shutdown_timeout", 10)

            try:
                proc.wait(timeout=test_timeout)
            except psutil.TimeoutExpired:
                test_timed_out = True
                proc.send_signal(signal.SIGTERM)

                try:
                    proc.wait(timeout=test_shutdown_timeout)
                except psutil.TimeoutExpired:
                    for child in proc.get_children(recursive=True):
                        child.send_signal(signal.SIGKILL)
                    proc.send_signal(signal.SIGKILL)


            # Take back signal handling from test running code
            signals_trigger_exit()


            try:
                result = result_queue.get_nowait()
            except multiprocessing.queues.Empty:
                result = Result(test, True, 0.0)

            if test_timed_out:
                result.aborted = False
            result_list.append(result)

            if not quiet and orig_stdin_termios is not None:
                try:
                    termios.tcsetattr(orig_stdin_fileno, termios.TCSANOW, orig_stdin_termios)
                except termios.error as err:
                    # I/O error caused by another test stopping this one
                    if err[0] == 5:
                        pass

            if quiet:
                sys.stdout = hijacked_stdout
                sys.stderr = hijacked_stderr

            if quiet and result is not None:
                if result.failure:
                    warn("X")
                else:
                    warn(".")

            if result.aborted:
                warn("Aborted\n")
                sys.exit(1)

            if self.settings.get('failfast', False) and result.failure:
                failedfast = True
                break
        return Results(result_list, failedfast, self.settings.get('colorless', False))
Example #52
0
 def grab_control(self, pgid):
     os.tcsetpgrp(self.__fd, pgid)
Example #53
0
 def to_foreground():
     os.tcsetpgrp(self._tty_fd.fileno(), pgid)
Example #54
0
def return_tty(fd, pgrp_id):
    try:
        os.tcsetpgrp(fd, pgrp_id)
    except OSError as oserr:
        #fails on s390 and s390x where we don't need it
        pass
Example #55
0
os.fstatvfs(fd)
# 返回包含文件描述符fd的文件的文件系统的信息,想stavfs()

os.fsync(fd)
# 强制将文件描述符为fd的文件写入硬盘

os.ftruncate(fd,length)
# 裁剪文件描述符fd对应的文件,所以它最大不能超过文件大小

os.isatty(fd)
# 如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回True,否则False

os.tcgetpgrp(fd)
# 返回与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组
	
os.tcsetpgrp(fd, pg)
# 设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg。

os.ttyname(fd)
# 返回一个字符串,它表示与文件描述符fd 关联的终端设备。如果fd 没有与终端设备关联,则引发一个异常


apue







Example #56
0
 def f(fd, pgrp):
     try:
         os.tcsetpgrp(fd, pgrp)
     except OSError:
         return 1
     return 0
Example #57
0
 def shell_to_foreground(self):
     # The shell should never accidentally stop itself.
     signal.signal(signal.SIGTTIN, signal.SIG_IGN)
     signal.signal(signal.SIGTTOU, signal.SIG_IGN)
     if self._tty_fd is not None:
         os.tcsetpgrp(self._tty_fd.fileno(), os.getpgrp())