Home | History | Annotate | Download | only in shill
      1 //
      2 // Copyright (C) 2013 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "shill/external_task.h"
     18 
     19 #include <base/bind.h>
     20 #include <base/bind_helpers.h>
     21 
     22 #include "shill/error.h"
     23 #include "shill/event_dispatcher.h"
     24 #include "shill/process_manager.h"
     25 
     26 namespace shill {
     27 
     28 using base::FilePath;
     29 using std::map;
     30 using std::string;
     31 using std::vector;
     32 
     33 ExternalTask::ExternalTask(
     34     ControlInterface* control,
     35     ProcessManager* process_manager,
     36     const base::WeakPtr<RPCTaskDelegate>& task_delegate,
     37     const base::Callback<void(pid_t, int)>& death_callback)
     38     : control_(control),
     39       process_manager_(process_manager),
     40       task_delegate_(task_delegate),
     41       death_callback_(death_callback),
     42       pid_(0) {
     43   CHECK(task_delegate_);
     44 }
     45 
     46 ExternalTask::~ExternalTask() {
     47   ExternalTask::Stop();
     48 }
     49 
     50 void ExternalTask::DestroyLater(EventDispatcher* dispatcher) {
     51   // Passes ownership of |this| to Destroy.
     52   dispatcher->PostTask(base::Bind(&Destroy, this));
     53 }
     54 
     55 bool ExternalTask::Start(const FilePath& program,
     56                          const vector<string>& arguments,
     57                          const map<string, string>& environment,
     58                          bool terminate_with_parent,
     59                          Error* error) {
     60   CHECK(!pid_);
     61   CHECK(!rpc_task_);
     62 
     63   // Setup full environment variables.
     64   std::unique_ptr<RPCTask> local_rpc_task(new RPCTask(control_, this));
     65   map<string, string> env = local_rpc_task->GetEnvironment();
     66   env.insert(environment.begin(), environment.end());
     67 
     68   pid_t pid =
     69       process_manager_->StartProcess(FROM_HERE,
     70                                      program,
     71                                      arguments,
     72                                      env,
     73                                      terminate_with_parent,
     74                                      base::Bind(&ExternalTask::OnTaskDied,
     75                                                 base::Unretained(this)));
     76 
     77   if (pid < 0) {
     78     Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError,
     79                           string("Unable to spawn: ") +
     80                           program.value().c_str());
     81     return false;
     82   }
     83   pid_ = pid;
     84   rpc_task_.reset(local_rpc_task.release());
     85   return true;
     86 }
     87 
     88 void ExternalTask::Stop() {
     89   if (pid_) {
     90     process_manager_->StopProcess(pid_);
     91     pid_ = 0;
     92   }
     93   rpc_task_.reset();
     94 }
     95 
     96 void ExternalTask::GetLogin(string* user, string* password) {
     97   return task_delegate_->GetLogin(user, password);
     98 }
     99 
    100 void ExternalTask::Notify(const string& event,
    101                           const map<string, string>& details) {
    102   return task_delegate_->Notify(event, details);
    103 }
    104 
    105 void ExternalTask::OnTaskDied(int exit_status) {
    106   CHECK(pid_);
    107   LOG(INFO) << __func__ << "(" << pid_ << ", "
    108             << exit_status << ")";
    109   death_callback_.Run(pid_, exit_status);
    110   pid_ = 0;
    111   rpc_task_.reset();
    112 }
    113 
    114 // static
    115 void ExternalTask::Destroy(ExternalTask* task) {
    116   delete task;
    117 }
    118 
    119 }  // namespace shill
    120