Esempio n. 1
0
void getfds(NetworkSocket fds[2]) {
  if (netops::socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) != 0) {
    FAIL() << "failed to create socketpair: " << errnoStr(errno);
  }
  for (int idx = 0; idx < 2; ++idx) {
    if (netops::set_socket_non_blocking(fds[idx]) != 0) {
      FAIL() << "failed to put socket " << idx
             << " in non-blocking mode: " << errnoStr(errno);
    }
  }
}
Esempio n. 2
0
int NestedCommandLineApp::run(const std::vector<std::string>& args) {
  int status;
  try {
    doRun(args);
    status = 0;
  } catch (const ProgramExit& ex) {
    if (ex.what()[0]) {  // if not empty
      fprintf(stderr, "%s\n", ex.what());
    }
    status = ex.status();
  } catch (const po::error& ex) {
    fprintf(stderr, "%s. Run `%s help' for help.\n",
            ex.what(), programName_.c_str());
    status = 1;
  }

  if (status == 0) {
    if (ferror(stdout)) {
      fprintf(stderr, "error on standard output\n");
      status = 1;
    } else if (fflush(stdout)) {
      fprintf(stderr, "standard output flush failed: %s\n",
              errnoStr(errno).c_str());
      status = 1;
    }
  }

  return status;
}
Esempio n. 3
0
SubprocessSpawnError::SubprocessSpawnError(const char* executable,
                                           int errCode,
                                           int errnoValue)
  : errnoValue_(errnoValue),
    what_(to<std::string>(errCode == kExecFailure ?
                            "failed to execute " :
                            "error preparing to execute ",
                          executable, ": ", errnoStr(errnoValue))) {
}
Esempio n. 4
0
AsyncIO::~AsyncIO() {
  CHECK_EQ(pending_, 0);
  if (ctx_) {
    int rc = io_queue_release(ctx_);
    CHECK_EQ(rc, 0) << "io_queue_release: " << errnoStr(-rc);
  }
  if (pollFd_ != -1) {
    CHECK_ERR(close(pollFd_));
  }
}
bool JemallocNodumpAllocator::extend_and_setup_arena() {
#ifdef FOLLY_JEMALLOC_NODUMP_ALLOCATOR_SUPPORTED
    if (mallctl == nullptr) {
        // Not linked with jemalloc.
        return false;
    }

    size_t len = sizeof(arena_index_);
    if (auto ret = mallctl("arenas.extend", &arena_index_, &len, nullptr, 0)) {
        LOG(FATAL) << "Unable to extend arena: " << errnoStr(ret);
    }
    flags_ = MALLOCX_ARENA(arena_index_) | MALLOCX_TCACHE_NONE;

    // Set the custom alloc hook
    const auto key =
        folly::to<std::string>("arena.", arena_index_, ".chunk_hooks");
    chunk_hooks_t hooks;
    len = sizeof(hooks);
    // Read the existing hooks
    if (auto ret = mallctl(key.c_str(), &hooks, &len, nullptr, 0)) {
        LOG(FATAL) << "Unable to get the hooks: " << errnoStr(ret);
    }
    if (original_chunk_alloc_ == nullptr) {
        original_chunk_alloc_ = hooks.alloc;
    } else {
        DCHECK_EQ(original_chunk_alloc_, hooks.alloc);
    }

    // Set the custom hook
    hooks.alloc = &JemallocNodumpAllocator::chunk_alloc;
    if (auto ret =
                mallctl(key.c_str(), nullptr, nullptr, &hooks, sizeof(hooks))) {
        LOG(FATAL) << "Unable to set the hooks: " << errnoStr(ret);
    }

    return true;
#else // FOLLY_JEMALLOC_NODUMP_ALLOCATOR_SUPPORTED
    return false;
#endif // FOLLY_JEMALLOC_NODUMP_ALLOCATOR_SUPPORTED
}
Esempio n. 6
0
std::ostream& operator<<(std::ostream& os, const AsyncIOOp& op) {
  os << "{" << op.state_ << ", ";

  if (op.state_ != AsyncIOOp::State::UNINITIALIZED) {
    os << op.iocb_;
  }

  if (op.state_ == AsyncIOOp::State::COMPLETED) {
    os << "result=" << op.result_;
    if (op.result_ < 0) {
      os << " (" << errnoStr(-op.result_) << ')';
    }
    os << ", ";
  }

  return os << "}";
}
void* JemallocNodumpAllocator::chunk_alloc(
    void* chunk,
    size_t size,
    size_t alignment,
    bool* zero,
    bool* commit,
    unsigned arena_ind) {
    void* result =
        original_chunk_alloc_(chunk, size, alignment, zero, commit, arena_ind);
    if (result != nullptr) {
        if (auto ret = madvise(result, size, MADV_DONTDUMP)) {
            VLOG(1) << "Unable to madvise(MADV_DONTDUMP): " << errnoStr(ret);
        }
    }

    return result;
}
Esempio n. 8
0
/* static */ std::string AsyncSocketException::getMessage(
    AsyncSocketExceptionType type,
    const std::string& message,
    int errnoCopy) {
  if (errnoCopy != 0) {
    return sformat(
        "AsyncSocketException: {}, type = {}, errno = {} ({})",
        message,
        getExceptionTypeString(type),
        errnoCopy,
        errnoStr(errnoCopy));
  } else {
    return sformat(
        "AsyncSocketException: {}, type = {}",
        message,
        getExceptionTypeString(type));
  }
}
Esempio n. 9
0
Range<AsyncIO::Op**> AsyncIO::doWait(size_t minRequests, size_t maxRequests) {
  io_event events[maxRequests];

  size_t count = 0;
  do {
    int ret;
    do {
      // GOTCHA: io_getevents() may returns less than min_nr results if
      // interrupted after some events have been read (if before, -EINTR
      // is returned).
      ret = io_getevents(ctx_,
                         minRequests - count,
                         maxRequests - count,
                         events + count,
                         /* timeout */ nullptr);  // wait forever
    } while (ret == -EINTR);
    // Check as may not be able to recover without leaking events.
    CHECK_GE(ret, 0)
      << "AsyncIO: io_getevents failed with error " << errnoStr(-ret);
    count += ret;
  } while (count < minRequests);
  DCHECK_LE(count, maxRequests);

  completed_.clear();
  if (count == 0) {
    return folly::Range<Op**>();
  }

  for (size_t i = 0; i < count; ++i) {
    DCHECK(events[i].obj);
    Op* op = boost::intrusive::get_parent_from_member(
        events[i].obj, &AsyncIOOp::iocb_);
    decrementPending();
    op->complete(events[i].res);
    completed_.push_back(op);
  }

  return folly::Range<Op**>(&completed_.front(), count);
}
Esempio n. 10
0
void Subprocess::spawnInternal(
    std::unique_ptr<const char*[]> argv,
    const char* executable,
    Options& options,
    const std::vector<std::string>* env,
    int errFd) {
  // Parent work, pre-fork: create pipes
  std::vector<int> childFds;
  // Close all of the childFds as we leave this scope
  SCOPE_EXIT {
    // These are only pipes, closing them shouldn't fail
    for (int cfd : childFds) {
      CHECK_ERR(::close(cfd));
    }
  };

  int r;
  for (auto& p : options.fdActions_) {
    if (p.second == PIPE_IN || p.second == PIPE_OUT) {
      int fds[2];
      r = ::pipe(fds);
      checkUnixError(r, "pipe");
      PipeInfo pinfo;
      pinfo.direction = p.second;
      int cfd;
      if (p.second == PIPE_IN) {
        // Child gets reading end
        pinfo.parentFd = fds[1];
        cfd = fds[0];
      } else {
        pinfo.parentFd = fds[0];
        cfd = fds[1];
      }
      p.second = cfd;  // ensure it gets dup2()ed
      pinfo.childFd = p.first;
      childFds.push_back(cfd);
      pipes_.push_back(pinfo);
    }
  }

  // This should already be sorted, as options.fdActions_ is
  DCHECK(std::is_sorted(pipes_.begin(), pipes_.end()));

  // Note that the const casts below are legit, per
  // http://pubs.opengroup.org/onlinepubs/009695399/functions/exec.html

  char** argVec = const_cast<char**>(argv.get());

  // Set up environment
  std::unique_ptr<const char*[]> envHolder;
  char** envVec;
  if (env) {
    envHolder = cloneStrings(*env);
    envVec = const_cast<char**>(envHolder.get());
  } else {
    envVec = environ;
  }

  // Block all signals around vfork; see http://ewontfix.com/7/.
  //
  // As the child may run in the same address space as the parent until
  // the actual execve() system call, any (custom) signal handlers that
  // the parent has might alter parent's memory if invoked in the child,
  // with undefined results.  So we block all signals in the parent before
  // vfork(), which will cause them to be blocked in the child as well (we
  // rely on the fact that Linux, just like all sane implementations, only
  // clones the calling thread).  Then, in the child, we reset all signals
  // to their default dispositions (while still blocked), and unblock them
  // (so the exec()ed process inherits the parent's signal mask)
  //
  // The parent also unblocks all signals as soon as vfork() returns.
  sigset_t allBlocked;
  r = sigfillset(&allBlocked);
  checkUnixError(r, "sigfillset");
  sigset_t oldSignals;

  r = pthread_sigmask(SIG_SETMASK, &allBlocked, &oldSignals);
  checkPosixError(r, "pthread_sigmask");
  SCOPE_EXIT {
    // Restore signal mask
    r = pthread_sigmask(SIG_SETMASK, &oldSignals, nullptr);
    CHECK_EQ(r, 0) << "pthread_sigmask: " << errnoStr(r);  // shouldn't fail
  };

  pid_t pid = vfork();
  if (pid == 0) {
    int errnoValue = prepareChild(options, &oldSignals);
    if (errnoValue != 0) {
      childError(errFd, kChildFailure, errnoValue);
    }

    errnoValue = runChild(executable, argVec, envVec, options);
    // If we get here, exec() failed.
    childError(errFd, kExecFailure, errnoValue);
  }
  // In parent.  Make sure vfork() succeeded.
  checkUnixError(pid, errno, "vfork");

  // Child is alive.  We have to be very careful about throwing after this
  // point.  We are inside the constructor, so if we throw the Subprocess
  // object will have never existed, and the destructor will never be called.
  //
  // We should only throw if we got an error via the errFd, and we know the
  // child has exited and can be immediately waited for.  In all other cases,
  // we have no way of cleaning up the child.
  pid_ = pid;
  returnCode_ = ProcessReturnCode(RV_RUNNING);
}