- add sources.
[platform/framework/web/crosswalk.git] / src / base / process / kill_posix.cc
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/process/kill.h"
6
7 #include <signal.h>
8 #include <sys/types.h>
9 #include <sys/wait.h>
10 #include <unistd.h>
11
12 #include "base/file_util.h"
13 #include "base/logging.h"
14 #include "base/posix/eintr_wrapper.h"
15 #include "base/process/process_iterator.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
18 #include "base/threading/platform_thread.h"
19
20 namespace base {
21
22 namespace {
23
24 int WaitpidWithTimeout(ProcessHandle handle,
25                        int64 wait_milliseconds,
26                        bool* success) {
27   // This POSIX version of this function only guarantees that we wait no less
28   // than |wait_milliseconds| for the process to exit.  The child process may
29   // exit sometime before the timeout has ended but we may still block for up
30   // to 256 milliseconds after the fact.
31   //
32   // waitpid() has no direct support on POSIX for specifying a timeout, you can
33   // either ask it to block indefinitely or return immediately (WNOHANG).
34   // When a child process terminates a SIGCHLD signal is sent to the parent.
35   // Catching this signal would involve installing a signal handler which may
36   // affect other parts of the application and would be difficult to debug.
37   //
38   // Our strategy is to call waitpid() once up front to check if the process
39   // has already exited, otherwise to loop for wait_milliseconds, sleeping for
40   // at most 256 milliseconds each time using usleep() and then calling
41   // waitpid().  The amount of time we sleep starts out at 1 milliseconds, and
42   // we double it every 4 sleep cycles.
43   //
44   // usleep() is speced to exit if a signal is received for which a handler
45   // has been installed.  This means that when a SIGCHLD is sent, it will exit
46   // depending on behavior external to this function.
47   //
48   // This function is used primarily for unit tests, if we want to use it in
49   // the application itself it would probably be best to examine other routes.
50   int status = -1;
51   pid_t ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
52   static const int64 kMaxSleepInMicroseconds = 1 << 18;  // ~256 milliseconds.
53   int64 max_sleep_time_usecs = 1 << 10;  // ~1 milliseconds.
54   int64 double_sleep_time = 0;
55
56   // If the process hasn't exited yet, then sleep and try again.
57   TimeTicks wakeup_time = TimeTicks::Now() +
58       TimeDelta::FromMilliseconds(wait_milliseconds);
59   while (ret_pid == 0) {
60     TimeTicks now = TimeTicks::Now();
61     if (now > wakeup_time)
62       break;
63     // Guaranteed to be non-negative!
64     int64 sleep_time_usecs = (wakeup_time - now).InMicroseconds();
65     // Sleep for a bit while we wait for the process to finish.
66     if (sleep_time_usecs > max_sleep_time_usecs)
67       sleep_time_usecs = max_sleep_time_usecs;
68
69     // usleep() will return 0 and set errno to EINTR on receipt of a signal
70     // such as SIGCHLD.
71     usleep(sleep_time_usecs);
72     ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
73
74     if ((max_sleep_time_usecs < kMaxSleepInMicroseconds) &&
75         (double_sleep_time++ % 4 == 0)) {
76       max_sleep_time_usecs *= 2;
77     }
78   }
79
80   if (success)
81     *success = (ret_pid != -1);
82
83   return status;
84 }
85
86 TerminationStatus GetTerminationStatusImpl(ProcessHandle handle,
87                                            bool can_block,
88                                            int* exit_code) {
89   int status = 0;
90   const pid_t result = HANDLE_EINTR(waitpid(handle, &status,
91                                             can_block ? 0 : WNOHANG));
92   if (result == -1) {
93     DPLOG(ERROR) << "waitpid(" << handle << ")";
94     if (exit_code)
95       *exit_code = 0;
96     return TERMINATION_STATUS_NORMAL_TERMINATION;
97   } else if (result == 0) {
98     // the child hasn't exited yet.
99     if (exit_code)
100       *exit_code = 0;
101     return TERMINATION_STATUS_STILL_RUNNING;
102   }
103
104   if (exit_code)
105     *exit_code = status;
106
107   if (WIFSIGNALED(status)) {
108     switch (WTERMSIG(status)) {
109       case SIGABRT:
110       case SIGBUS:
111       case SIGFPE:
112       case SIGILL:
113       case SIGSEGV:
114         return TERMINATION_STATUS_PROCESS_CRASHED;
115       case SIGINT:
116       case SIGKILL:
117       case SIGTERM:
118         return TERMINATION_STATUS_PROCESS_WAS_KILLED;
119       default:
120         break;
121     }
122   }
123
124   if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
125     return TERMINATION_STATUS_ABNORMAL_TERMINATION;
126
127   return TERMINATION_STATUS_NORMAL_TERMINATION;
128 }
129
130 }  // namespace
131
132 // Attempts to kill the process identified by the given process
133 // entry structure.  Ignores specified exit_code; posix can't force that.
134 // Returns true if this is successful, false otherwise.
135 bool KillProcess(ProcessHandle process_id, int exit_code, bool wait) {
136   DCHECK_GT(process_id, 1) << " tried to kill invalid process_id";
137   if (process_id <= 1)
138     return false;
139   bool result = kill(process_id, SIGTERM) == 0;
140   if (result && wait) {
141     int tries = 60;
142
143     if (RunningOnValgrind()) {
144       // Wait for some extra time when running under Valgrind since the child
145       // processes may take some time doing leak checking.
146       tries *= 2;
147     }
148
149     unsigned sleep_ms = 4;
150
151     // The process may not end immediately due to pending I/O
152     bool exited = false;
153     while (tries-- > 0) {
154       pid_t pid = HANDLE_EINTR(waitpid(process_id, NULL, WNOHANG));
155       if (pid == process_id) {
156         exited = true;
157         break;
158       }
159       if (pid == -1) {
160         if (errno == ECHILD) {
161           // The wait may fail with ECHILD if another process also waited for
162           // the same pid, causing the process state to get cleaned up.
163           exited = true;
164           break;
165         }
166         DPLOG(ERROR) << "Error waiting for process " << process_id;
167       }
168
169       usleep(sleep_ms * 1000);
170       const unsigned kMaxSleepMs = 1000;
171       if (sleep_ms < kMaxSleepMs)
172         sleep_ms *= 2;
173     }
174
175     // If we're waiting and the child hasn't died by now, force it
176     // with a SIGKILL.
177     if (!exited)
178       result = kill(process_id, SIGKILL) == 0;
179   }
180
181   if (!result)
182     DPLOG(ERROR) << "Unable to terminate process " << process_id;
183
184   return result;
185 }
186
187 bool KillProcessGroup(ProcessHandle process_group_id) {
188   bool result = kill(-1 * process_group_id, SIGKILL) == 0;
189   if (!result)
190     DPLOG(ERROR) << "Unable to terminate process group " << process_group_id;
191   return result;
192 }
193
194 TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
195   return GetTerminationStatusImpl(handle, false /* can_block */, exit_code);
196 }
197
198 TerminationStatus GetKnownDeadTerminationStatus(ProcessHandle handle,
199                                                 int* exit_code) {
200   bool result = kill(handle, SIGKILL) == 0;
201
202   if (!result)
203     DPLOG(ERROR) << "Unable to terminate process " << handle;
204
205   return GetTerminationStatusImpl(handle, true /* can_block */, exit_code);
206 }
207
208 bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
209   int status;
210   if (HANDLE_EINTR(waitpid(handle, &status, 0)) == -1) {
211     NOTREACHED();
212     return false;
213   }
214
215   if (WIFEXITED(status)) {
216     *exit_code = WEXITSTATUS(status);
217     return true;
218   }
219
220   // If it didn't exit cleanly, it must have been signaled.
221   DCHECK(WIFSIGNALED(status));
222   return false;
223 }
224
225 bool WaitForExitCodeWithTimeout(ProcessHandle handle,
226                                 int* exit_code,
227                                 base::TimeDelta timeout) {
228   bool waitpid_success = false;
229   int status = WaitpidWithTimeout(handle, timeout.InMilliseconds(),
230                                   &waitpid_success);
231   if (status == -1)
232     return false;
233   if (!waitpid_success)
234     return false;
235   if (WIFSIGNALED(status)) {
236     *exit_code = -1;
237     return true;
238   }
239   if (WIFEXITED(status)) {
240     *exit_code = WEXITSTATUS(status);
241     return true;
242   }
243   return false;
244 }
245
246 bool WaitForProcessesToExit(const FilePath::StringType& executable_name,
247                             base::TimeDelta wait,
248                             const ProcessFilter* filter) {
249   bool result = false;
250
251   // TODO(port): This is inefficient, but works if there are multiple procs.
252   // TODO(port): use waitpid to avoid leaving zombies around
253
254   base::TimeTicks end_time = base::TimeTicks::Now() + wait;
255   do {
256     NamedProcessIterator iter(executable_name, filter);
257     if (!iter.NextProcessEntry()) {
258       result = true;
259       break;
260     }
261     base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
262   } while ((end_time - base::TimeTicks::Now()) > base::TimeDelta());
263
264   return result;
265 }
266
267 #if defined(OS_MACOSX)
268 // Using kqueue on Mac so that we can wait on non-child processes.
269 // We can't use kqueues on child processes because we need to reap
270 // our own children using wait.
271 static bool WaitForSingleNonChildProcess(ProcessHandle handle,
272                                          base::TimeDelta wait) {
273   DCHECK_GT(handle, 0);
274   DCHECK(wait.InMilliseconds() == base::kNoTimeout || wait > base::TimeDelta());
275
276   int kq = kqueue();
277   if (kq == -1) {
278     DPLOG(ERROR) << "kqueue";
279     return false;
280   }
281   file_util::ScopedFD kq_closer(&kq);
282
283   struct kevent change = {0};
284   EV_SET(&change, handle, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
285   int result = HANDLE_EINTR(kevent(kq, &change, 1, NULL, 0, NULL));
286   if (result == -1) {
287     if (errno == ESRCH) {
288       // If the process wasn't found, it must be dead.
289       return true;
290     }
291
292     DPLOG(ERROR) << "kevent (setup " << handle << ")";
293     return false;
294   }
295
296   // Keep track of the elapsed time to be able to restart kevent if it's
297   // interrupted.
298   bool wait_forever = wait.InMilliseconds() == base::kNoTimeout;
299   base::TimeDelta remaining_delta;
300   base::TimeTicks deadline;
301   if (!wait_forever) {
302     remaining_delta = wait;
303     deadline = base::TimeTicks::Now() + remaining_delta;
304   }
305
306   result = -1;
307   struct kevent event = {0};
308
309   while (wait_forever || remaining_delta > base::TimeDelta()) {
310     struct timespec remaining_timespec;
311     struct timespec* remaining_timespec_ptr;
312     if (wait_forever) {
313       remaining_timespec_ptr = NULL;
314     } else {
315       remaining_timespec = remaining_delta.ToTimeSpec();
316       remaining_timespec_ptr = &remaining_timespec;
317     }
318
319     result = kevent(kq, NULL, 0, &event, 1, remaining_timespec_ptr);
320
321     if (result == -1 && errno == EINTR) {
322       if (!wait_forever) {
323         remaining_delta = deadline - base::TimeTicks::Now();
324       }
325       result = 0;
326     } else {
327       break;
328     }
329   }
330
331   if (result < 0) {
332     DPLOG(ERROR) << "kevent (wait " << handle << ")";
333     return false;
334   } else if (result > 1) {
335     DLOG(ERROR) << "kevent (wait " << handle << "): unexpected result "
336                 << result;
337     return false;
338   } else if (result == 0) {
339     // Timed out.
340     return false;
341   }
342
343   DCHECK_EQ(result, 1);
344
345   if (event.filter != EVFILT_PROC ||
346       (event.fflags & NOTE_EXIT) == 0 ||
347       event.ident != static_cast<uintptr_t>(handle)) {
348     DLOG(ERROR) << "kevent (wait " << handle
349                 << "): unexpected event: filter=" << event.filter
350                 << ", fflags=" << event.fflags
351                 << ", ident=" << event.ident;
352     return false;
353   }
354
355   return true;
356 }
357 #endif  // OS_MACOSX
358
359 bool WaitForSingleProcess(ProcessHandle handle, base::TimeDelta wait) {
360   ProcessHandle parent_pid = GetParentProcessId(handle);
361   ProcessHandle our_pid = Process::Current().handle();
362   if (parent_pid != our_pid) {
363 #if defined(OS_MACOSX)
364     // On Mac we can wait on non child processes.
365     return WaitForSingleNonChildProcess(handle, wait);
366 #else
367     // Currently on Linux we can't handle non child processes.
368     NOTIMPLEMENTED();
369 #endif  // OS_MACOSX
370   }
371
372   bool waitpid_success;
373   int status = -1;
374   if (wait.InMilliseconds() == base::kNoTimeout) {
375     waitpid_success = (HANDLE_EINTR(waitpid(handle, &status, 0)) != -1);
376   } else {
377     status = WaitpidWithTimeout(
378         handle, wait.InMilliseconds(), &waitpid_success);
379   }
380
381   if (status != -1) {
382     DCHECK(waitpid_success);
383     return WIFEXITED(status);
384   } else {
385     return false;
386   }
387 }
388
389 bool CleanupProcesses(const FilePath::StringType& executable_name,
390                       base::TimeDelta wait,
391                       int exit_code,
392                       const ProcessFilter* filter) {
393   bool exited_cleanly = WaitForProcessesToExit(executable_name, wait, filter);
394   if (!exited_cleanly)
395     KillProcesses(executable_name, exit_code, filter);
396   return exited_cleanly;
397 }
398
399 #if !defined(OS_MACOSX)
400
401 namespace {
402
403 // Return true if the given child is dead. This will also reap the process.
404 // Doesn't block.
405 static bool IsChildDead(pid_t child) {
406   const pid_t result = HANDLE_EINTR(waitpid(child, NULL, WNOHANG));
407   if (result == -1) {
408     DPLOG(ERROR) << "waitpid(" << child << ")";
409     NOTREACHED();
410   } else if (result > 0) {
411     // The child has died.
412     return true;
413   }
414
415   return false;
416 }
417
418 // A thread class which waits for the given child to exit and reaps it.
419 // If the child doesn't exit within a couple of seconds, kill it.
420 class BackgroundReaper : public PlatformThread::Delegate {
421  public:
422   BackgroundReaper(pid_t child, unsigned timeout)
423       : child_(child),
424         timeout_(timeout) {
425   }
426
427   // Overridden from PlatformThread::Delegate:
428   virtual void ThreadMain() OVERRIDE {
429     WaitForChildToDie();
430     delete this;
431   }
432
433   void WaitForChildToDie() {
434     // Wait forever case.
435     if (timeout_ == 0) {
436       pid_t r = HANDLE_EINTR(waitpid(child_, NULL, 0));
437       if (r != child_) {
438         DPLOG(ERROR) << "While waiting for " << child_
439                      << " to terminate, we got the following result: " << r;
440       }
441       return;
442     }
443
444     // There's no good way to wait for a specific child to exit in a timed
445     // fashion. (No kqueue on Linux), so we just loop and sleep.
446
447     // Wait for 2 * timeout_ 500 milliseconds intervals.
448     for (unsigned i = 0; i < 2 * timeout_; ++i) {
449       PlatformThread::Sleep(TimeDelta::FromMilliseconds(500));
450       if (IsChildDead(child_))
451         return;
452     }
453
454     if (kill(child_, SIGKILL) == 0) {
455       // SIGKILL is uncatchable. Since the signal was delivered, we can
456       // just wait for the process to die now in a blocking manner.
457       if (HANDLE_EINTR(waitpid(child_, NULL, 0)) < 0)
458         DPLOG(WARNING) << "waitpid";
459     } else {
460       DLOG(ERROR) << "While waiting for " << child_ << " to terminate we"
461                   << " failed to deliver a SIGKILL signal (" << errno << ").";
462     }
463   }
464
465  private:
466   const pid_t child_;
467   // Number of seconds to wait, if 0 then wait forever and do not attempt to
468   // kill |child_|.
469   const unsigned timeout_;
470
471   DISALLOW_COPY_AND_ASSIGN(BackgroundReaper);
472 };
473
474 }  // namespace
475
476 void EnsureProcessTerminated(ProcessHandle process) {
477   // If the child is already dead, then there's nothing to do.
478   if (IsChildDead(process))
479     return;
480
481   const unsigned timeout = 2;  // seconds
482   BackgroundReaper* reaper = new BackgroundReaper(process, timeout);
483   PlatformThread::CreateNonJoinable(0, reaper);
484 }
485
486 void EnsureProcessGetsReaped(ProcessHandle process) {
487   // If the child is already dead, then there's nothing to do.
488   if (IsChildDead(process))
489     return;
490
491   BackgroundReaper* reaper = new BackgroundReaper(process, 0);
492   PlatformThread::CreateNonJoinable(0, reaper);
493 }
494
495 #endif  // !defined(OS_MACOSX)
496
497 }  // namespace base