diff options
author | dmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-24 17:14:36 +0000 |
---|---|---|
committer | dmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-24 17:14:36 +0000 |
commit | 56f0f264ff866052ebcb24e75147cb600e6547a1 (patch) | |
tree | 8b16bded93f914cacbf3cb130fae3539ad4bb268 /base | |
parent | 04a8454da64b62bfad5091efd5cf1143443283f0 (diff) | |
download | chromium_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.h | 14 | ||||
-rw-r--r-- | base/process_util_mac.mm | 13 | ||||
-rw-r--r-- | base/process_util_posix.cc | 82 | ||||
-rw-r--r-- | base/process_util_unittest.cc | 4 |
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) |