OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "update_engine/subprocess.h" | 5 #include "update_engine/subprocess.h" |
6 #include <stdlib.h> | 6 #include <stdlib.h> |
7 #include <string.h> | 7 #include <string.h> |
8 #include <string> | 8 #include <string> |
9 #include <unistd.h> | 9 #include <unistd.h> |
10 #include <vector> | 10 #include <vector> |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
(...skipping 22 matching lines...) Expand all Loading... |
34 } | 34 } |
35 | 35 |
36 namespace { | 36 namespace { |
37 void FreeArgv(char** argv) { | 37 void FreeArgv(char** argv) { |
38 for (int i = 0; argv[i]; i++) { | 38 for (int i = 0; argv[i]; i++) { |
39 free(argv[i]); | 39 free(argv[i]); |
40 argv[i] = NULL; | 40 argv[i] = NULL; |
41 } | 41 } |
42 } | 42 } |
43 | 43 |
| 44 void FreeArgvInError(char** argv) { |
| 45 FreeArgv(argv); |
| 46 LOG(ERROR) << "Ran out of memory copying args."; |
| 47 } |
| 48 |
44 // Note: Caller responsible for free()ing the returned value! | 49 // Note: Caller responsible for free()ing the returned value! |
| 50 // Will return NULL on failure and free any allocated memory. |
45 char** ArgPointer() { | 51 char** ArgPointer() { |
46 const char* keys[] = {"LD_LIBRARY_PATH", "PATH"}; | 52 const char* keys[] = {"LD_LIBRARY_PATH", "PATH"}; |
47 char** ret = new char*[arraysize(keys) + 1]; | 53 char** ret = new char*[arraysize(keys) + 1]; |
48 int pointer = 0; | 54 int pointer = 0; |
49 for (size_t i = 0; i < arraysize(keys); i++) { | 55 for (size_t i = 0; i < arraysize(keys); i++) { |
50 ret[i] = NULL; | |
51 if (getenv(keys[i])) { | 56 if (getenv(keys[i])) { |
52 ret[pointer] = strdup(StringPrintf("%s=%s", keys[i], | 57 ret[pointer] = strdup(StringPrintf("%s=%s", keys[i], |
53 getenv(keys[i])).c_str()); | 58 getenv(keys[i])).c_str()); |
54 pointer++; | 59 if (!ret[pointer]) { |
| 60 FreeArgv(ret); |
| 61 delete [] ret; |
| 62 return NULL; |
| 63 } |
| 64 ++pointer; |
55 } | 65 } |
56 } | 66 } |
| 67 ret[pointer] = NULL; |
57 return ret; | 68 return ret; |
58 } | 69 } |
59 | 70 |
60 class ScopedFreeArgPointer { | 71 class ScopedFreeArgPointer { |
61 public: | 72 public: |
62 ScopedFreeArgPointer(char** arr) : arr_(arr) {} | 73 ScopedFreeArgPointer(char** arr) : arr_(arr) {} |
63 ~ScopedFreeArgPointer() { | 74 ~ScopedFreeArgPointer() { |
64 if (!arr_) | 75 if (!arr_) |
65 return; | 76 return; |
66 for (int i = 0; arr_[i]; i++) | 77 for (int i = 0; arr_[i]; i++) |
67 free(arr_[i]); | 78 free(arr_[i]); |
68 delete[] arr_; | 79 delete[] arr_; |
69 } | 80 } |
70 private: | 81 private: |
71 char** arr_; | 82 char** arr_; |
72 DISALLOW_COPY_AND_ASSIGN(ScopedFreeArgPointer); | 83 DISALLOW_COPY_AND_ASSIGN(ScopedFreeArgPointer); |
73 }; | 84 }; |
74 } // namespace {} | 85 } // namespace {} |
75 | 86 |
76 uint32_t Subprocess::Exec(const std::vector<std::string>& cmd, | 87 uint32_t Subprocess::Exec(const std::vector<std::string>& cmd, |
77 ExecCallback callback, | 88 ExecCallback callback, |
78 void* p) { | 89 void* p) { |
79 GPid child_pid; | 90 GPid child_pid; |
80 GError* err; | 91 GError* err; |
81 scoped_array<char*> argv(new char*[cmd.size() + 1]); | 92 scoped_array<char*> argv(new char*[cmd.size() + 1]); |
82 for (unsigned int i = 0; i < cmd.size(); i++) { | 93 for (unsigned int i = 0; i < cmd.size(); i++) { |
83 argv[i] = strdup(cmd[i].c_str()); | 94 argv[i] = strdup(cmd[i].c_str()); |
| 95 if (!argv[i]) { |
| 96 FreeArgvInError(argv.get()); // NULL in argv[i] terminates argv. |
| 97 return 0; |
| 98 } |
84 } | 99 } |
85 argv[cmd.size()] = NULL; | 100 argv[cmd.size()] = NULL; |
86 | 101 |
87 char** argp = ArgPointer(); | 102 char** argp = ArgPointer(); |
| 103 if (!argp) { |
| 104 FreeArgvInError(argv.get()); // NULL in argv[i] terminates argv. |
| 105 return 0; |
| 106 } |
88 ScopedFreeArgPointer argp_free(argp); | 107 ScopedFreeArgPointer argp_free(argp); |
89 | 108 |
90 SubprocessCallbackRecord callback_record; | 109 SubprocessCallbackRecord callback_record; |
91 callback_record.callback = callback; | 110 callback_record.callback = callback; |
92 callback_record.callback_data = p; | 111 callback_record.callback_data = p; |
93 | 112 |
94 bool success = g_spawn_async(NULL, // working directory | 113 bool success = g_spawn_async(NULL, // working directory |
95 argv.get(), | 114 argv.get(), |
96 argp, | 115 argp, |
97 G_SPAWN_DO_NOT_REAP_CHILD, // flags | 116 G_SPAWN_DO_NOT_REAP_CHILD, // flags |
(...skipping 17 matching lines...) Expand all Loading... |
115 callback_records_[tag].callback = NULL; | 134 callback_records_[tag].callback = NULL; |
116 } | 135 } |
117 } | 136 } |
118 | 137 |
119 bool Subprocess::SynchronousExec(const std::vector<std::string>& cmd, | 138 bool Subprocess::SynchronousExec(const std::vector<std::string>& cmd, |
120 int* return_code) { | 139 int* return_code) { |
121 GError* err = NULL; | 140 GError* err = NULL; |
122 scoped_array<char*> argv(new char*[cmd.size() + 1]); | 141 scoped_array<char*> argv(new char*[cmd.size() + 1]); |
123 for (unsigned int i = 0; i < cmd.size(); i++) { | 142 for (unsigned int i = 0; i < cmd.size(); i++) { |
124 argv[i] = strdup(cmd[i].c_str()); | 143 argv[i] = strdup(cmd[i].c_str()); |
| 144 if (!argv[i]) { |
| 145 FreeArgvInError(argv.get()); // NULL in argv[i] terminates argv. |
| 146 return false; |
| 147 } |
125 } | 148 } |
126 argv[cmd.size()] = NULL; | 149 argv[cmd.size()] = NULL; |
127 | 150 |
128 char** argp = ArgPointer(); | 151 char** argp = ArgPointer(); |
| 152 if (!argp) { |
| 153 FreeArgvInError(argv.get()); // NULL in argv[i] terminates argv. |
| 154 return false; |
| 155 } |
129 ScopedFreeArgPointer argp_free(argp); | 156 ScopedFreeArgPointer argp_free(argp); |
130 | 157 |
131 char* child_stdout; | 158 char* child_stdout; |
132 | 159 |
133 bool success = g_spawn_sync(NULL, // working directory | 160 bool success = g_spawn_sync(NULL, // working directory |
134 argv.get(), | 161 argv.get(), |
135 argp, | 162 argp, |
136 G_SPAWN_STDERR_TO_DEV_NULL, // flags | 163 G_SPAWN_STDERR_TO_DEV_NULL, // flags |
137 GRedirectStderrToStdout, // child setup function | 164 GRedirectStderrToStdout, // child setup function |
138 NULL, // data for child setup function | 165 NULL, // data for child setup function |
139 &child_stdout, | 166 &child_stdout, |
140 NULL, | 167 NULL, |
141 return_code, | 168 return_code, |
142 &err); | 169 &err); |
143 FreeArgv(argv.get()); | 170 FreeArgv(argv.get()); |
144 if (err) | 171 if (err) |
145 LOG(INFO) << "err is: " << err->code << ", " << err->message; | 172 LOG(INFO) << "err is: " << err->code << ", " << err->message; |
146 if (child_stdout && strlen(child_stdout)) | 173 if (child_stdout && strlen(child_stdout)) |
147 LOG(INFO) << "Subprocess output:\n" << child_stdout; | 174 LOG(INFO) << "Subprocess output:\n" << child_stdout; |
148 return success; | 175 return success; |
149 } | 176 } |
150 | 177 |
151 Subprocess* Subprocess::subprocess_singleton_ = NULL; | 178 Subprocess* Subprocess::subprocess_singleton_ = NULL; |
152 | 179 |
153 } // namespace chromeos_update_engine | 180 } // namespace chromeos_update_engine |
OLD | NEW |