예제 #1
0
  def _CheckStatus(self, status, node):
    """Raises ErrExitFailure, maybe with location info attached."""
    if self.exec_opts.ErrExit() and status != 0:
      # NOTE: Sometimes location info is duplicated, like on UsageError, or a
      # bad redirect.  Also, pipelines can fail twice.

      if node.tag == command_e.SimpleCommand:
        reason = 'command in '
        span_id = word.LeftMostSpanForWord(node.words[0])
      elif node.tag == command_e.Assignment:
        reason = 'assignment in '
        span_id = self._SpanIdForAssignment(node)
      elif node.tag == command_e.Subshell:
        reason = 'subshell invoked from '
        span_id = node.spids[0]
      elif node.tag == command_e.Pipeline:
        # The whole pipeline can fail separately
        reason = 'pipeline invoked from '
        span_id = node.spids[0]  # only one spid
      else:
        # NOTE: The fallback of CurrentSpanId() fills this in.
        reason = ''
        span_id = const.NO_INTEGER

      raise util.ErrExitFailure(
          'Exiting with status %d (%sPID %d)', status, reason, posix.getpid(),
          span_id=span_id, status=status)
예제 #2
0
  def _CheckStatus(self, status, node, argv0=None):
    """ErrExitFailure with location info attached."""
    if self.exec_opts.ErrExit() and status != 0:
      # Add context based on node type
      if node.tag == command_e.SimpleCommand:
        argv0 = argv0 or '<unknown>'
        raise util.ErrExitFailure(
            '[%d] %r command exited with status %d', posix.getpid(), argv0,
            status, word=node.words[0], status=status)
      elif node.tag == command_e.Assignment:
        span_id = self._SpanIdForAssignment(node)
        raise util.ErrExitFailure(
            '[%d] assignment exited with status %d', posix.getpid(),
            status, span_id=span_id, status=status)

      else:
        raise util.ErrExitFailure(
            '[%d] %r exited with status %d', posix.getpid(),
            node.__class__.__name__, status, status=status)
예제 #3
0
  def RunCommandSub(self, node):
    p = self._MakeProcess(node,
                          disable_errexit=not self.exec_opts.strict_errexit)

    r, w = posix.pipe()
    p.AddStateChange(process.StdoutToPipe(r, w))
    pid = p.Start()
    #log('Command sub started %d', pid)
    self.waiter.Register(pid, p.WhenDone)

    chunks = []
    posix.close(w)  # not going to write
    while True:
      byte_str = posix.read(r, 4096)
      if not byte_str:
        break
      chunks.append(byte_str)
    posix.close(r)

    status = p.WaitUntilDone(self.waiter)

    # OSH has the concept of aborting in the middle of a WORD.  We're not
    # waiting until the command is over!
    if self.exec_opts.strict_errexit:
      if self.exec_opts.ErrExit() and status != 0:
        raise util.ErrExitFailure(
            'Command sub exited with status %d (%r)', status,
            node.__class__.__name__)
    else:
      # Set a flag so we check errexit at the same time as bash.  Example:
      #
      # a=$(false)
      # echo foo  # no matter what comes here, the flag is reset
      #
      # Set ONLY until this command node has finished executing.
      self.check_command_sub_status = True
      self.mem.last_status = status

    # Runtime errors test case: # $("echo foo > $@")
    # Why rstrip()?
    # https://unix.stackexchange.com/questions/17747/why-does-shell-command-substitution-gobble-up-a-trailing-newline-char
    return ''.join(chunks).rstrip('\n')