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 26namespace shill { 27 28using base::FilePath; 29using std::map; 30using std::string; 31using std::vector; 32 33ExternalTask::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 46ExternalTask::~ExternalTask() { 47 ExternalTask::Stop(); 48} 49 50void ExternalTask::DestroyLater(EventDispatcher* dispatcher) { 51 // Passes ownership of |this| to Destroy. 52 dispatcher->PostTask(base::Bind(&Destroy, this)); 53} 54 55bool 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 88void ExternalTask::Stop() { 89 if (pid_) { 90 process_manager_->StopProcess(pid_); 91 pid_ = 0; 92 } 93 rpc_task_.reset(); 94} 95 96void ExternalTask::GetLogin(string* user, string* password) { 97 return task_delegate_->GetLogin(user, password); 98} 99 100void ExternalTask::Notify(const string& event, 101 const map<string, string>& details) { 102 return task_delegate_->Notify(event, details); 103} 104 105void 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 115void ExternalTask::Destroy(ExternalTask* task) { 116 delete task; 117} 118 119} // namespace shill 120