Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Side by Side Diff: user_collector.cc

Issue 3755011: crash-reporter: Avoid using system to invoke core2md (Closed) Base URL: http://git.chromium.org/git/crash-reporter.git
Patch Set: Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « user_collector.h ('k') | user_collector_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2010 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 "crash-reporter/user_collector.h" 5 #include "crash-reporter/user_collector.h"
6 6
7 #include <fcntl.h> // For creat.
7 #include <grp.h> // For struct group. 8 #include <grp.h> // For struct group.
8 #include <pwd.h> // For struct passwd. 9 #include <pwd.h> // For struct passwd.
9 #include <sys/types.h> // For getpwuid_r and getgrnam_r. 10 #include <sys/types.h> // For getpwuid_r, getgrnam_r, WEXITSTATUS.
11 #include <sys/wait.h> // For waitpid.
12 #include <unistd.h> // For execv and fork.
10 13
11 #include <string> 14 #include <string>
15 #include <vector>
12 16
17 #include "base/eintr_wrapper.h"
13 #include "base/file_util.h" 18 #include "base/file_util.h"
14 #include "base/logging.h" 19 #include "base/logging.h"
15 #include "base/string_util.h" 20 #include "base/string_util.h"
16 #include "crash-reporter/system_logging.h" 21 #include "crash-reporter/system_logging.h"
17 22
18 // This procfs file is used to cause kernel core file writing to 23 // This procfs file is used to cause kernel core file writing to
19 // instead pipe the core file into a user space process. See 24 // instead pipe the core file into a user space process. See
20 // core(5) man page. 25 // core(5) man page.
21 static const char kCorePatternFile[] = "/proc/sys/kernel/core_pattern"; 26 static const char kCorePatternFile[] = "/proc/sys/kernel/core_pattern";
22 static const char kCoreToMinidumpConverterPath[] = "/usr/bin/core2md"; 27 static const char kCoreToMinidumpConverterPath[] = "/usr/bin/core2md";
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 if (file_util::CopyFile(stdin_path, core_path)) { 202 if (file_util::CopyFile(stdin_path, core_path)) {
198 return true; 203 return true;
199 } 204 }
200 205
201 logger_->LogError("Could not write core file"); 206 logger_->LogError("Could not write core file");
202 // If the file system was full, make sure we remove any remnants. 207 // If the file system was full, make sure we remove any remnants.
203 file_util::Delete(core_path, false); 208 file_util::Delete(core_path, false);
204 return false; 209 return false;
205 } 210 }
206 211
212 int UserCollector::ForkExecAndPipe(std::vector<const char *> &arguments,
213 const char *output_file) {
214 // Copy off a writeable version of arguments.
215 scoped_array<char*> argv(new char *[arguments.size() + 1]);
216 int total_args_size = 0;
217 for (size_t i = 0; i < arguments.size(); ++i) {
218 if (arguments[i] == NULL) {
219 logger_->LogError("Bad parameter");
220 return -1;
221 }
222 total_args_size += strlen(arguments[i]) + 1;
223 }
224 scoped_array<char> buffer(new char[total_args_size]);
225 char *buffer_pointer = &buffer[0];
226
227 for (size_t i = 0; i < arguments.size(); ++i) {
228 argv[i] = buffer_pointer;
229 strcpy(buffer_pointer, arguments[i]);
230 buffer_pointer += strlen(arguments[i]);
231 *buffer_pointer = '\0';
232 ++buffer_pointer;
233 }
234 argv[arguments.size()] = NULL;
235
236 int pid = fork();
237 if (pid < 0) {
238 logger_->LogError("Fork failed: %d", errno);
239 return -1;
240 }
241
242 if (pid == 0) {
243 int output_handle = creat(output_file, 0700);
244 if (output_handle < 0) {
245 logger_->LogError("Could not create %s: %d", output_file, errno);
246 // Avoid exit() to avoid atexit handlers from parent.
247 _exit(127);
248 }
249 dup2(output_handle, 1);
250 dup2(output_handle, 2);
251 execv(argv[0], &argv[0]);
252 logger_->LogError("Exec failed: %d", errno);
253 _exit(127);
254 }
255
256 int status = 0;
257 if (HANDLE_EINTR(waitpid(pid, &status, 0)) < 0) {
258 logger_->LogError("Problem waiting for pid: %d", errno);
259 return -1;
260 }
261 if (!WIFEXITED(status)) {
262 logger_->LogError("Process did not exit normally: %x", status);
263 return -1;
264 }
265 return WEXITSTATUS(status);
266 }
267
207 bool UserCollector::ConvertCoreToMinidump(const FilePath &core_path, 268 bool UserCollector::ConvertCoreToMinidump(const FilePath &core_path,
208 const FilePath &procfs_directory, 269 const FilePath &procfs_directory,
209 const FilePath &minidump_path, 270 const FilePath &minidump_path,
210 const FilePath &temp_directory) { 271 const FilePath &temp_directory) {
211 // TODO(kmixter): Rewrite to use process_util once it's included in
212 // libchrome.
213 FilePath output_path = temp_directory.Append("output"); 272 FilePath output_path = temp_directory.Append("output");
214 std::string core2md_command = 273 std::vector<const char *> core2md_arguments;
215 StringPrintf("\"%s\" \"%s\" \"%s\" \"%s\" > \"%s\" 2>&1", 274 core2md_arguments.push_back(kCoreToMinidumpConverterPath);
216 kCoreToMinidumpConverterPath, 275 core2md_arguments.push_back(core_path.value().c_str());
217 core_path.value().c_str(), 276 core2md_arguments.push_back(procfs_directory.value().c_str());
218 procfs_directory.value().c_str(), 277 core2md_arguments.push_back(minidump_path.value().c_str());
219 minidump_path.value().c_str(), 278
220 output_path.value().c_str()); 279 int errorlevel = ForkExecAndPipe(core2md_arguments,
221 int errorlevel = system(core2md_command.c_str()); 280 output_path.value().c_str());
222 281
223 std::string output; 282 std::string output;
224 file_util::ReadFileToString(output_path, &output); 283 file_util::ReadFileToString(output_path, &output);
225 if (errorlevel != 0) { 284 if (errorlevel != 0) {
226 logger_->LogInfo("Problem during %s [result=%d]: %s", 285 logger_->LogInfo("Problem during %s [result=%d]: %s",
227 core2md_command.c_str(), 286 kCoreToMinidumpConverterPath,
228 errorlevel, 287 errorlevel,
229 output.c_str()); 288 output.c_str());
230 return false; 289 return false;
231 } 290 }
232 291
233 if (!file_util::PathExists(minidump_path)) { 292 if (!file_util::PathExists(minidump_path)) {
234 logger_->LogError("Minidump file %s was not created", 293 logger_->LogError("Minidump file %s was not created",
235 minidump_path.value().c_str()); 294 minidump_path.value().c_str());
236 return false; 295 return false;
237 } 296 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 369
311 if (feedback) { 370 if (feedback) {
312 count_crash_function_(); 371 count_crash_function_();
313 372
314 if (generate_diagnostics_) { 373 if (generate_diagnostics_) {
315 return GenerateDiagnostics(pid, exec); 374 return GenerateDiagnostics(pid, exec);
316 } 375 }
317 } 376 }
318 return true; 377 return true;
319 } 378 }
OLDNEW
« no previous file with comments | « user_collector.h ('k') | user_collector_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698