Coverage for /Syzygy/kasko/upload_thread.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
71.4%50700.C++source

Line-by-line coverage:

   1    :  // Copyright 2014 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #include "syzygy/kasko/upload_thread.h"
  16    :  
  17    :  #include <windows.h>
  18    :  #include "base/logging.h"
  19    :  #include "base/files/file_path.h"
  20    :  #include "base/strings/string16.h"
  21    :  #include "base/strings/string_util.h"
  22    :  #include "syzygy/common/com_utils.h"
  23    :  #include "syzygy/kasko/waitable_timer.h"
  24    :  
  25    :  namespace kasko {
  26    :  
  27    :  // static
  28    :  scoped_ptr<UploadThread> UploadThread::Create(
  29    :      const base::FilePath& exclusive_path,
  30    :      scoped_ptr<WaitableTimer> waitable_timer,
  31  E :      const base::Closure& uploader) {
  32    :    // '\' is the only character not permitted in mutex names.
  33  E :    base::string16 escaped_path;
  34  E :    base::ReplaceChars(exclusive_path.value(), L"\\", L"/", &escaped_path);
  35  E :    base::string16 mutex_name = L"Local\\kasko_uploader_mutex_" + escaped_path;
  36    :    base::string16 wake_event_name =
  37  E :        L"Local\\kasko_uploader_wake_event_" + escaped_path;
  38  E :    base::win::ScopedHandle mutex(::CreateMutex(NULL, FALSE, mutex_name.c_str()));
  39  E :    if (!mutex) {
  40  i :      DWORD error = ::GetLastError();
  41  i :      LOG(ERROR) << "Failed to create a mutex named " << mutex_name << ": "
  42    :                 << ::common::LogWe(error);
  43  i :      return scoped_ptr<UploadThread>();
  44    :    }
  45  E :    base::win::ScopedHandle stop_event(::CreateEvent(NULL, TRUE, FALSE, NULL));
  46  E :    if (!stop_event) {
  47  i :      DWORD error = ::GetLastError();
  48  i :      LOG(ERROR) << "Failed to create an event: " << ::common::LogWe(error);
  49  i :      return scoped_ptr<UploadThread>();
  50    :    }
  51    :    base::win::ScopedHandle wake_event(
  52  E :        ::CreateEvent(NULL, FALSE, FALSE, wake_event_name.c_str()));
  53  E :    if (!wake_event) {
  54  i :      DWORD error = ::GetLastError();
  55  i :      LOG(ERROR) << "Failed to create an event named '" << wake_event_name
  56    :                 << "': " << ::common::LogWe(error);
  57  i :      return scoped_ptr<UploadThread>();
  58    :    }
  59    :    return make_scoped_ptr(new UploadThread(mutex.Pass(), stop_event.Pass(),
  60    :                                            wake_event.Pass(),
  61  E :                                            waitable_timer.Pass(), uploader));
  62  E :  }
  63    :  
  64  E :  UploadThread::~UploadThread() {
  65    :    // It's a bad idea to shut down without stopping the service. It's also a bad
  66    :    // idea to block unexpectedly in our destructor.
  67  E :    CHECK(!thread_impl_.HasBeenStarted() || thread_impl_.HasBeenJoined());
  68  E :  }
  69    :  
  70  E :  void UploadThread::Start() {
  71  E :    thread_impl_.Start();
  72  E :  }
  73    :  
  74  E :  void UploadThread::Stop() {
  75  E :    if (!::SetEvent(stop_event_)) {
  76  i :      DWORD error = ::GetLastError();
  77  i :      LOG(FATAL) << "Failed to signal stop event. Terminating to avoid deadlock: "
  78    :                 << ::common::LogWe(error);
  79    :    }
  80  E :  }
  81    :  
  82  E :  void UploadThread::Join() {
  83  E :    Stop();
  84  E :    thread_impl_.Join();
  85  E :  }
  86    :  
  87  E :  void UploadThread::UploadOneNowAsync() {
  88  E :    if (!::SetEvent(wake_event_)) {
  89  i :      DWORD error = ::GetLastError();
  90  i :      LOG(ERROR) << "Failed to signal wake event: " << ::common::LogWe(error);
  91    :    }
  92  E :  }
  93    :  
  94    :  UploadThread::ThreadImpl::ThreadImpl(UploadThread* owner)
  95  E :      : base::SimpleThread("upload_thread"), owner_(owner) {
  96  E :  }
  97    :  
  98  E :  UploadThread::ThreadImpl::~ThreadImpl(){}
  99    :  
 100  E :  void UploadThread::ThreadImpl::Run() {
 101  E :    HANDLE handles_pre_mutex[] = {owner_->mutex_, owner_->stop_event_};
 102    :    DWORD wait_result = ::WaitForMultipleObjects(
 103  E :        arraysize(handles_pre_mutex), handles_pre_mutex, FALSE, INFINITE);
 104  E :    switch (wait_result) {
 105    :      case WAIT_OBJECT_0:
 106    :      case WAIT_ABANDONED_0:
 107    :        // mutex_
 108  E :        break;
 109    :      case WAIT_OBJECT_0 + 1:
 110    :        // stop_event_
 111  i :        return;
 112    :      default:
 113  i :        DWORD error = ::GetLastError();
 114  i :        LOG(ERROR) << "WaitForMultipleObjects failed: " << ::common::LogWe(error);
 115  i :        return;
 116    :    }
 117    :  
 118    :    // We have the mutex now. We will wait on the wake event, the stop event, and
 119    :    // the timer.
 120    :    HANDLE handles_post_mutex[] = {owner_->wake_event_,
 121    :                                   owner_->stop_event_,
 122  E :                                   owner_->waitable_timer_->GetHANDLE()};
 123    :  
 124  E :    while (true) {
 125  E :      owner_->waitable_timer_->Start();
 126    :      wait_result = ::WaitForMultipleObjects(arraysize(handles_post_mutex),
 127  E :                                             handles_post_mutex, FALSE, INFINITE);
 128  E :      switch (wait_result) {
 129    :        case WAIT_OBJECT_0:
 130    :          // wake_event_
 131  E :          break;
 132    :        case WAIT_OBJECT_0 + 1:
 133    :          // stop_event_
 134  E :          return;
 135    :        case WAIT_OBJECT_0 + 2:
 136    :          // waitable_timer_
 137  E :          break;
 138    :        default:
 139  i :          DWORD error = ::GetLastError();
 140  i :          LOG(ERROR) << "WaitForMultipleObjects failed: "
 141    :                     << ::common::LogWe(error);
 142  i :          return;
 143    :      }
 144  E :      owner_->uploader_.Run();
 145  E :    }
 146  E :  }
 147    :  
 148    :  UploadThread::UploadThread(base::win::ScopedHandle mutex,
 149    :                             base::win::ScopedHandle stop_event,
 150    :                             base::win::ScopedHandle wake_event,
 151    :                             scoped_ptr<WaitableTimer> waitable_timer,
 152    :                             const base::Closure& uploader)
 153    :      : mutex_(mutex.Take()),
 154    :        stop_event_(stop_event.Take()),
 155    :        wake_event_(wake_event.Take()),
 156    :        waitable_timer_(waitable_timer.Pass()),
 157    :        uploader_(uploader),
 158  E :        thread_impl_(this) {
 159  E :  }
 160    :  
 161    :  }  // namespace kasko

Coverage information generated Thu Mar 26 16:15:41 2015.