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
ExternalTask(ControlInterface * control,ProcessManager * process_manager,const base::WeakPtr<RPCTaskDelegate> & task_delegate,const base::Callback<void (pid_t,int)> & death_callback)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
~ExternalTask()46 ExternalTask::~ExternalTask() {
47 ExternalTask::Stop();
48 }
49
DestroyLater(EventDispatcher * dispatcher)50 void ExternalTask::DestroyLater(EventDispatcher* dispatcher) {
51 // Passes ownership of |this| to Destroy.
52 dispatcher->PostTask(base::Bind(&Destroy, this));
53 }
54
Start(const FilePath & program,const vector<string> & arguments,const map<string,string> & environment,bool terminate_with_parent,Error * error)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
Stop()88 void ExternalTask::Stop() {
89 if (pid_) {
90 process_manager_->StopProcess(pid_);
91 pid_ = 0;
92 }
93 rpc_task_.reset();
94 }
95
GetLogin(string * user,string * password)96 void ExternalTask::GetLogin(string* user, string* password) {
97 return task_delegate_->GetLogin(user, password);
98 }
99
Notify(const string & event,const map<string,string> & details)100 void ExternalTask::Notify(const string& event,
101 const map<string, string>& details) {
102 return task_delegate_->Notify(event, details);
103 }
104
OnTaskDied(int exit_status)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
Destroy(ExternalTask * task)115 void ExternalTask::Destroy(ExternalTask* task) {
116 delete task;
117 }
118
119 } // namespace shill
120