summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authordmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-24 17:14:36 +0000
committerdmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-24 17:14:36 +0000
commit56f0f264ff866052ebcb24e75147cb600e6547a1 (patch)
tree8b16bded93f914cacbf3cb130fae3539ad4bb268 /base
parent04a8454da64b62bfad5091efd5cf1143443283f0 (diff)
downloadchromium_src-56f0f264ff866052ebcb24e75147cb600e6547a1.zip
chromium_src-56f0f264ff866052ebcb24e75147cb600e6547a1.tar.gz
chromium_src-56f0f264ff866052ebcb24e75147cb600e6547a1.tar.bz2
Get service process running standalone on the mac by hooking it into launchd.
BUG=NONE TEST=BUILD Review URL: http://codereview.chromium.org/6482016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75893 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/process_util.h14
-rw-r--r--base/process_util_mac.mm13
-rw-r--r--base/process_util_posix.cc82
-rw-r--r--base/process_util_unittest.cc4
4 files changed, 101 insertions, 12 deletions
diff --git a/base/process_util.h b/base/process_util.h
index a7f8496..29b08ca 100644
--- a/base/process_util.h
+++ b/base/process_util.h
@@ -162,9 +162,6 @@ void CloseProcessHandle(ProcessHandle process);
ProcessId GetProcId(ProcessHandle process);
#if defined(OS_LINUX)
-// Returns the ID for the parent of the given process.
-ProcessId GetParentProcessId(ProcessHandle process);
-
// Returns the path to the executable of the given process.
FilePath GetProcessExecutablePath(ProcessHandle process);
@@ -182,6 +179,9 @@ bool AdjustOOMScore(ProcessId process, int score);
#endif
#if defined(OS_POSIX)
+// Returns the ID for the parent of the given process.
+ProcessId GetParentProcessId(ProcessHandle process);
+
// Close all file descriptors, except those which are a destination in the
// given multimap. Only call this function in a child process where you know
// that there aren't any other threads.
@@ -359,7 +359,7 @@ bool KillProcessById(ProcessId process_id, int exit_code, bool wait);
// will no longer be available).
TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code);
-// Waits for process to exit. In POSIX systems, if the process hasn't been
+// Waits for process to exit. On POSIX systems, if the process hasn't been
// signaled then puts the exit code in |exit_code|; otherwise it's considered
// a failure. On Windows |exit_code| is always filled. Returns true on success,
// and closes |handle| in any case.
@@ -382,9 +382,9 @@ bool WaitForProcessesToExit(const FilePath::StringType& executable_name,
const ProcessFilter* filter);
// Wait for a single process to exit. Return true if it exited cleanly within
-// the given time limit.
-bool WaitForSingleProcess(ProcessHandle handle,
- int64 wait_milliseconds);
+// the given time limit. On Linux |handle| must be a child process, however
+// on Mac and Windows it can be any process.
+bool WaitForSingleProcess(ProcessHandle handle, int64 wait_milliseconds);
// Returns true when |wait_milliseconds| have elapsed and the process
// is still running.
diff --git a/base/process_util_mac.mm b/base/process_util_mac.mm
index aa0f14d..6d05581 100644
--- a/base/process_util_mac.mm
+++ b/base/process_util_mac.mm
@@ -880,4 +880,17 @@ void EnableTerminationOnOutOfMemory() {
reinterpret_cast<IMP>(oom_killer_allocWithZone));
}
+ProcessId GetParentProcessId(ProcessHandle process) {
+ struct kinfo_proc info;
+ size_t length = sizeof(struct kinfo_proc);
+ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process };
+ if (sysctl(mib, 4, &info, &length, NULL, 0) < 0) {
+ PLOG(ERROR) << "sysctl";
+ return -1;
+ }
+ if (length == 0)
+ return -1;
+ return info.kp_eproc.e_ppid;
+}
+
} // namespace base
diff --git a/base/process_util_posix.cc b/base/process_util_posix.cc
index 9d0ba58..9a5f5a7 100644
--- a/base/process_util_posix.cc
+++ b/base/process_util_posix.cc
@@ -32,6 +32,7 @@
#if defined(OS_MACOSX)
#include <crt_externs.h>
+#include <sys/event.h>
#define environ (*_NSGetEnviron())
#else
extern char** environ;
@@ -496,17 +497,20 @@ bool LaunchAppImpl(
scoped_array<char*> new_environ(AlterEnvironment(env_changes, environ));
pid = fork();
- if (pid < 0)
+ if (pid < 0) {
+ PLOG(ERROR) << "fork";
return false;
-
+ }
if (pid == 0) {
// Child process
if (start_new_process_group) {
// Instead of inheriting the process group ID of the parent, the child
// starts off a new process group with pgid equal to its process ID.
- if (setpgid(0, 0) < 0)
+ if (setpgid(0, 0) < 0) {
+ PLOG(ERROR) << "setpgid";
return false;
+ }
}
#if defined(OS_MACOSX)
RestoreDefaultExceptionHandler();
@@ -713,7 +717,79 @@ bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code,
return true;
}
+#if defined(OS_MACOSX)
+// Using kqueue on Mac so that we can wait on non-child processes.
+// We can't use kqueues on child processes because we need to reap
+// our own children using wait.
+static bool WaitForSingleNonChildProcess(ProcessHandle handle,
+ int64 wait_milliseconds) {
+ int kq = kqueue();
+ if (kq == -1) {
+ PLOG(ERROR) << "kqueue";
+ return false;
+ }
+
+ struct kevent change = { 0 };
+ EV_SET(&change, handle, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
+
+ struct timespec spec;
+ struct timespec *spec_ptr;
+ if (wait_milliseconds != base::kNoTimeout) {
+ time_t sec = static_cast<time_t>(wait_milliseconds / 1000);
+ wait_milliseconds = wait_milliseconds - (sec * 1000);
+ spec.tv_sec = sec;
+ spec.tv_nsec = wait_milliseconds * 1000000L;
+ spec_ptr = &spec;
+ } else {
+ spec_ptr = NULL;
+ }
+
+ while(true) {
+ struct kevent event = { 0 };
+ int event_count = HANDLE_EINTR(kevent(kq, &change, 1, &event, 1, spec_ptr));
+ if (close(kq) != 0) {
+ PLOG(ERROR) << "close";
+ }
+ if (event_count < 0) {
+ PLOG(ERROR) << "kevent";
+ return false;
+ } else if (event_count == 0) {
+ if (wait_milliseconds != base::kNoTimeout) {
+ // Timed out.
+ return false;
+ }
+ } else if ((event_count == 1) &&
+ (handle == static_cast<pid_t>(event.ident)) &&
+ (event.filter == EVFILT_PROC)) {
+ if (event.fflags == NOTE_EXIT) {
+ return true;
+ } else if (event.flags == EV_ERROR) {
+ LOG(ERROR) << "kevent error " << event.data;
+ return false;
+ } else {
+ NOTREACHED();
+ return false;
+ }
+ } else {
+ NOTREACHED();
+ return false;
+ }
+ }
+}
+#endif // OS_MACOSX
+
bool WaitForSingleProcess(ProcessHandle handle, int64 wait_milliseconds) {
+ ProcessHandle parent_pid = GetParentProcessId(handle);
+ ProcessHandle our_pid = Process::Current().handle();
+ if (parent_pid != our_pid) {
+#if defined(OS_MACOSX)
+ // On Mac we can wait on non child processes.
+ return WaitForSingleNonChildProcess(handle, wait_milliseconds);
+#else
+ // Currently on Linux we can't handle non child processes.
+ NOTIMPLEMENTED();
+#endif // OS_MACOSX
+ }
bool waitpid_success;
int status;
if (wait_milliseconds == base::kNoTimeout)
diff --git a/base/process_util_unittest.cc b/base/process_util_unittest.cc
index 1b7368a..31e1dec 100644
--- a/base/process_util_unittest.cc
+++ b/base/process_util_unittest.cc
@@ -658,12 +658,12 @@ TEST_F(ProcessUtilTest, GetAppOutputRestrictedNoZombies) {
}
}
-#if defined(OS_LINUX)
TEST_F(ProcessUtilTest, GetParentProcessId) {
base::ProcessId ppid = base::GetParentProcessId(base::GetCurrentProcId());
EXPECT_EQ(ppid, getppid());
}
+#if defined(OS_LINUX)
TEST_F(ProcessUtilTest, ParseProcStatCPU) {
// /proc/self/stat for a process running "top".
const char kTopStat[] = "960 (top) S 16230 960 16230 34818 960 "
@@ -683,7 +683,7 @@ TEST_F(ProcessUtilTest, ParseProcStatCPU) {
EXPECT_EQ(0, base::ParseProcStatCPU(kSelfStat));
}
-#endif
+#endif // defined(OS_LINUX)
#endif // defined(OS_POSIX)