Beispiel #1
0
    def Run(self):
        """
    do_exit: For small pipelines
    """
        #log('Writing %r', self.body_str)
        posix.write(self.w, self.body_str)
        #log('Wrote %r', self.body_str)
        posix.close(self.w)
        #log('Closed %d', self.w)

        sys.exit(0)  # Could this fail?
Beispiel #2
0
    def testWrite(self):
        if posix_.environ.get('EINTR_TEST'):

            signal.signal(signal.SIGTERM, _Handler)
            r, w = posix_.pipe()
            log('Hanging on write in pid %d', posix_.getpid())

            # 1 byte bigger than pipe size
            n = posix_.write(w, 'x' * 65537)
            log('1: Wrote %d bytes', n)

            # write returns early when a signal interrupts it, and we read at least
            # one byte!  We do NOT get EINTR>

            # On the second try, it didn't write anything, and we get EINTR!

            log('Second try (pid %d)', posix_.getpid())
            n = posix_.write(w, 'x' * 65537)
            log('2: Wrote %d bytes', n)
Beispiel #3
0
    def _ApplyRedirect(self, r, waiter):
        # type: (redirect, Waiter) -> None
        arg = r.arg
        UP_arg = arg
        with tagswitch(arg) as case:

            if case(redirect_arg_e.Path):
                arg = cast(redirect_arg__Path, UP_arg)

                if r.op_id in (Id.Redir_Great, Id.Redir_AndGreat):  # >   &>
                    # NOTE: This is different than >| because it respects noclobber, but
                    # that option is almost never used.  See test/wild.sh.
                    mode = posix.O_CREAT | posix.O_WRONLY | posix.O_TRUNC
                elif r.op_id == Id.Redir_Clobber:  # >|
                    mode = posix.O_CREAT | posix.O_WRONLY | posix.O_TRUNC
                elif r.op_id in (Id.Redir_DGreat,
                                 Id.Redir_AndDGreat):  # >>   &>>
                    mode = posix.O_CREAT | posix.O_WRONLY | posix.O_APPEND
                elif r.op_id == Id.Redir_Less:  # <
                    mode = posix.O_RDONLY
                elif r.op_id == Id.Redir_LessGreat:  # <>
                    mode = posix.O_CREAT | posix.O_RDWR
                else:
                    raise NotImplementedError(r.op_id)

                # NOTE: 0666 is affected by umask, all shells use it.
                try:
                    open_fd = posix.open(arg.filename, mode, 0o666)
                except OSError as e:
                    self.errfmt.Print_("Can't open %r: %s" %
                                       (arg.filename, pyutil.strerror(e)),
                                       span_id=r.op_spid)
                    raise  # redirect failed

                new_fd = self._PushDup(open_fd, r.loc)
                if new_fd != NO_FD:
                    posix.close(open_fd)

                # Now handle &> and &>> and their variants.  These pairs are the same:
                #
                #   stdout_stderr.py &> out-err.txt
                #   stdout_stderr.py > out-err.txt 2>&1
                #
                #   stdout_stderr.py 3&> out-err.txt
                #   stdout_stderr.py 3> out-err.txt 2>&3
                #
                # Ditto for {fd}> and {fd}&>

                if r.op_id in (Id.Redir_AndGreat, Id.Redir_AndDGreat):
                    self._PushDup(new_fd, redir_loc.Fd(2))

            elif case(redirect_arg_e.CopyFd):  # e.g. echo hi 1>&2
                arg = cast(redirect_arg__CopyFd, UP_arg)

                if r.op_id == Id.Redir_GreatAnd:  # 1>&2
                    self._PushDup(arg.target_fd, r.loc)

                elif r.op_id == Id.Redir_LessAnd:  # 0<&5
                    # The only difference between >& and <& is the default file
                    # descriptor argument.
                    self._PushDup(arg.target_fd, r.loc)

                else:
                    raise NotImplementedError()

            elif case(redirect_arg_e.MoveFd):  # e.g. echo hi 5>&6-
                arg = cast(redirect_arg__MoveFd, UP_arg)
                new_fd = self._PushDup(arg.target_fd, r.loc)
                if new_fd != NO_FD:
                    posix.close(arg.target_fd)

                    UP_loc = r.loc
                    if r.loc.tag_() == redir_loc_e.Fd:
                        fd = cast(redir_loc__Fd, UP_loc).fd
                    else:
                        fd = NO_FD

                    self.cur_frame.saved.append(_RedirFrame(new_fd, fd, False))

            elif case(redirect_arg_e.CloseFd):  # e.g. echo hi 5>&-
                self._PushCloseFd(r.loc)

            elif case(redirect_arg_e.HereDoc):
                arg = cast(redirect_arg__HereDoc, UP_arg)

                # NOTE: Do these descriptors have to be moved out of the range 0-9?
                read_fd, write_fd = posix.pipe()

                self._PushDup(read_fd, r.loc)  # stdin is now the pipe

                # We can't close like we do in the filename case above?  The writer can
                # get a "broken pipe".
                self._PushClose(read_fd)

                thunk = _HereDocWriterThunk(write_fd, arg.body)

                # TODO: Use PIPE_SIZE to save a process in the case of small here docs,
                # which are the common case.  (dash does this.)
                start_process = True
                #start_process = False

                if start_process:
                    here_proc = Process(thunk, self.job_state)

                    # NOTE: we could close the read pipe here, but it doesn't really
                    # matter because we control the code.
                    _ = here_proc.Start()
                    #log('Started %s as %d', here_proc, pid)
                    self._PushWait(here_proc, waiter)

                    # Now that we've started the child, close it in the parent.
                    posix.close(write_fd)

                else:
                    posix.write(write_fd, arg.body)
                    posix.close(write_fd)
Beispiel #4
0
 def testEmptyReadAndWrite(self):
     # Regression for bug where this would hang
     posix_.read(0, 0)
     posix_.write(1, '')
Beispiel #5
0
  def _ApplyRedirect(self, r, waiter):
    # type: (redirect_t, Waiter) -> bool
    ok = True

    UP_r = r
    with tagswitch(r) as case:

      if case(redirect_e.Path):
        r = cast(redirect__Path, UP_r)

        if r.op_id in (Id.Redir_Great, Id.Redir_AndGreat):  # >   &>
          # NOTE: This is different than >| because it respects noclobber, but
          # that option is almost never used.  See test/wild.sh.
          mode = posix.O_CREAT | posix.O_WRONLY | posix.O_TRUNC
        elif r.op_id == Id.Redir_Clobber:  # >|
          mode = posix.O_CREAT | posix.O_WRONLY | posix.O_TRUNC
        elif r.op_id in (Id.Redir_DGreat, Id.Redir_AndDGreat):  # >>   &>>
          mode = posix.O_CREAT | posix.O_WRONLY | posix.O_APPEND
        elif r.op_id == Id.Redir_Less:  # <
          mode = posix.O_RDONLY
        else:
          raise NotImplementedError(r.op_id)

        # NOTE: 0666 is affected by umask, all shells use it.
        try:
          target_fd = posix.open(r.filename, mode, 0o666)
        except OSError as e:
          self.errfmt.Print(
              "Can't open %r: %s", r.filename, posix.strerror(e.errno),
              span_id=r.op_spid)
          return False

        # Apply redirect
        if not self._PushDup(target_fd, r.fd):
          ok = False

        # Now handle the extra redirects for aliases &> and &>>.
        #
        # We can rewrite
        #   stdout_stderr.py &> out-err.txt
        # as
        #   stdout_stderr.py > out-err.txt 2>&1
        #
        # And rewrite
        #   stdout_stderr.py 3&> out-err.txt
        # as
        #   stdout_stderr.py 3> out-err.txt 2>&3
        if ok:
          if r.op_id == Id.Redir_AndGreat:
            if not self._PushDup(r.fd, 2):
              ok = False
          elif r.op_id == Id.Redir_AndDGreat:
            if not self._PushDup(r.fd, 2):
              ok = False

        posix.close(target_fd)  # We already made a copy of it.
        # I don't think we need to close(0) because it will be restored from its
        # saved position (10), which closes it.
        #self._PushClose(r.fd)

      elif case(redirect_e.FileDesc):  # e.g. echo hi 1>&2
        r = cast(redirect__FileDesc, UP_r)

        if r.op_id == Id.Redir_GreatAnd:  # 1>&2
          if not self._PushDup(r.target_fd, r.fd):
            ok = False
        elif r.op_id == Id.Redir_LessAnd:  # 0<&5
          # The only difference between >& and <& is the default file
          # descriptor argument.
          if not self._PushDup(r.target_fd, r.fd):
            ok = False
        else:
          raise NotImplementedError()

      elif case(redirect_e.HereDoc):
        r = cast(redirect__HereDoc, UP_r)

        # NOTE: Do these descriptors have to be moved out of the range 0-9?
        read_fd, write_fd = posix.pipe()

        if not self._PushDup(read_fd, r.fd):  # stdin is now the pipe
          ok = False

        # We can't close like we do in the filename case above?  The writer can
        # get a "broken pipe".
        self._PushClose(read_fd)

        thunk = _HereDocWriterThunk(write_fd, r.body)

        # TODO: Use PIPE_SIZE to save a process in the case of small here docs,
        # which are the common case.  (dash does this.)
        start_process = True
        #start_process = False

        if start_process:
          here_proc = Process(thunk, self.job_state)

          # NOTE: we could close the read pipe here, but it doesn't really
          # matter because we control the code.
          _ = here_proc.Start()
          #log('Started %s as %d', here_proc, pid)
          self._PushWait(here_proc, waiter)

          # Now that we've started the child, close it in the parent.
          posix.close(write_fd)

        else:
          posix.write(write_fd, r.body)
          posix.close(write_fd)

    return ok