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