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