libchrome: Uprev the library to r456626 from Chromium
Pulled the latest and greatest version of libchrome from Chromium.
The merge was done against r456626 which corresponds to git commit
08266b3fca707804065a2cfd60331722ade41969 of Mar 14, 2017
Notable changes are:
- FOR_EACH_OBSERVER macro removed (replaced by use of C++ 11
range-base for loop)
- base::Values no more FundamentalValue
- stl_util moved to base namespace
- some scoped pointers removed in crypto/ in favor
of BoringSSL UniquePtr.
- path() accessor renamed to GetPath() in ScopedTempDir (and other
classes)
- introduction of base::CallbackOnce
Test: All unit-tests should still pass.
Change-Id: I180f9defc7607f462389fae17701fff553c4a2d0
diff --git a/base/process/launch_mac.cc b/base/process/launch_mac.cc
index 5895eae..3732bc1 100644
--- a/base/process/launch_mac.cc
+++ b/base/process/launch_mac.cc
@@ -4,13 +4,75 @@
#include "base/process/launch.h"
+#include <crt_externs.h>
#include <mach/mach.h>
-#include <servers/bootstrap.h>
+#include <spawn.h>
+#include <string.h>
+#include <sys/wait.h>
#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/threading/thread_restrictions.h"
namespace base {
+namespace {
+
+// DPSXCHECK is a Debug Posix Spawn Check macro. The posix_spawn* family of
+// functions return an errno value, as opposed to setting errno directly. This
+// macro emulates a DPCHECK().
+#define DPSXCHECK(expr) \
+ do { \
+ int rv = (expr); \
+ DCHECK_EQ(rv, 0) << #expr << ": -" << rv << " " << strerror(rv); \
+ } while (0)
+
+class PosixSpawnAttr {
+ public:
+ PosixSpawnAttr() { DPSXCHECK(posix_spawnattr_init(&attr_)); }
+
+ ~PosixSpawnAttr() { DPSXCHECK(posix_spawnattr_destroy(&attr_)); }
+
+ posix_spawnattr_t* get() { return &attr_; }
+
+ private:
+ posix_spawnattr_t attr_;
+};
+
+class PosixSpawnFileActions {
+ public:
+ PosixSpawnFileActions() {
+ DPSXCHECK(posix_spawn_file_actions_init(&file_actions_));
+ }
+
+ ~PosixSpawnFileActions() {
+ DPSXCHECK(posix_spawn_file_actions_destroy(&file_actions_));
+ }
+
+ void Open(int filedes, const char* path, int mode) {
+ DPSXCHECK(posix_spawn_file_actions_addopen(&file_actions_, filedes, path,
+ mode, 0));
+ }
+
+ void Dup2(int filedes, int newfiledes) {
+ DPSXCHECK(
+ posix_spawn_file_actions_adddup2(&file_actions_, filedes, newfiledes));
+ }
+
+ void Inherit(int filedes) {
+ DPSXCHECK(posix_spawn_file_actions_addinherit_np(&file_actions_, filedes));
+ }
+
+ const posix_spawn_file_actions_t* get() const { return &file_actions_; }
+
+ private:
+ posix_spawn_file_actions_t file_actions_;
+
+ DISALLOW_COPY_AND_ASSIGN(PosixSpawnFileActions);
+};
+
+} // namespace
+
void RestoreDefaultExceptionHandler() {
// This function is tailored to remove the Breakpad exception handler.
// exception_mask matches s_exception_mask in
@@ -28,4 +90,93 @@
EXCEPTION_DEFAULT, THREAD_STATE_NONE);
}
+Process LaunchProcessPosixSpawn(const std::vector<std::string>& argv,
+ const LaunchOptions& options) {
+ DCHECK(!options.pre_exec_delegate)
+ << "LaunchProcessPosixSpawn does not support PreExecDelegate";
+ DCHECK(options.current_directory.empty())
+ << "LaunchProcessPosixSpawn does not support current_directory";
+
+ PosixSpawnAttr attr;
+
+ short flags = POSIX_SPAWN_CLOEXEC_DEFAULT;
+ if (options.new_process_group) {
+ flags |= POSIX_SPAWN_SETPGROUP;
+ DPSXCHECK(posix_spawnattr_setpgroup(attr.get(), 0));
+ }
+ DPSXCHECK(posix_spawnattr_setflags(attr.get(), flags));
+
+ PosixSpawnFileActions file_actions;
+
+ // Process file descriptors for the child. By default, LaunchProcess will
+ // open stdin to /dev/null and inherit stdout and stderr.
+ bool inherit_stdout = true, inherit_stderr = true;
+ bool null_stdin = true;
+ if (options.fds_to_remap) {
+ for (const auto& dup2_pair : *options.fds_to_remap) {
+ if (dup2_pair.second == STDIN_FILENO) {
+ null_stdin = false;
+ } else if (dup2_pair.second == STDOUT_FILENO) {
+ inherit_stdout = false;
+ } else if (dup2_pair.second == STDERR_FILENO) {
+ inherit_stderr = false;
+ }
+
+ if (dup2_pair.first == dup2_pair.second) {
+ file_actions.Inherit(dup2_pair.second);
+ } else {
+ file_actions.Dup2(dup2_pair.first, dup2_pair.second);
+ }
+ }
+ }
+
+ if (null_stdin) {
+ file_actions.Open(STDIN_FILENO, "/dev/null", O_RDONLY);
+ }
+ if (inherit_stdout) {
+ file_actions.Inherit(STDOUT_FILENO);
+ }
+ if (inherit_stderr) {
+ file_actions.Inherit(STDERR_FILENO);
+ }
+
+ std::unique_ptr<char* []> argv_cstr(new char*[argv.size() + 1]);
+ for (size_t i = 0; i < argv.size(); i++) {
+ argv_cstr[i] = const_cast<char*>(argv[i].c_str());
+ }
+ argv_cstr[argv.size()] = nullptr;
+
+ std::unique_ptr<char* []> owned_environ;
+ char** new_environ = options.clear_environ ? nullptr : *_NSGetEnviron();
+ if (!options.environ.empty()) {
+ owned_environ = AlterEnvironment(new_environ, options.environ);
+ new_environ = owned_environ.get();
+ }
+
+ const char* executable_path = !options.real_path.empty()
+ ? options.real_path.value().c_str()
+ : argv_cstr[0];
+
+ // Use posix_spawnp as some callers expect to have PATH consulted.
+ pid_t pid;
+ int rv = posix_spawnp(&pid, executable_path, file_actions.get(), attr.get(),
+ &argv_cstr[0], new_environ);
+
+ if (rv != 0) {
+ DLOG(ERROR) << "posix_spawnp(" << executable_path << "): -" << rv << " "
+ << strerror(rv);
+ return Process();
+ }
+
+ if (options.wait) {
+ // While this isn't strictly disk IO, waiting for another process to
+ // finish is the sort of thing ThreadRestrictions is trying to prevent.
+ base::ThreadRestrictions::AssertIOAllowed();
+ pid_t ret = HANDLE_EINTR(waitpid(pid, nullptr, 0));
+ DPCHECK(ret > 0);
+ }
+
+ return Process(pid);
+}
+
} // namespace base