blob: 89b6cadd03fd56fa88ecf875d78a6040cedee9ca [file] [log] [blame]
adlr@google.com3defe6a2009-12-04 20:57:17 +00001// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "update_engine/subprocess.h"
6#include <stdlib.h>
7#include <string.h>
8#include <string>
9#include <vector>
10#include "chromeos/obsolete_logging.h"
11#include "base/scoped_ptr.h"
12
13using std::string;
14using std::vector;
15
16namespace chromeos_update_engine {
17
18void Subprocess::GChildExitedCallback(GPid pid, gint status, gpointer data) {
19 COMPILE_ASSERT(sizeof(guint) == sizeof(uint32),
20 guint_uint32_size_mismatch);
21 guint *tag = reinterpret_cast<guint*>(data);
22 const SubprocessCallbackRecord& record = Get().callback_records_[*tag];
23 if (record.callback)
24 record.callback(status, record.callback_data);
25 g_spawn_close_pid(pid);
26 Get().callback_records_.erase(*tag);
27 delete tag;
28}
29
30namespace {
31void FreeArgv(char** argv) {
32 for (int i = 0; argv[i]; i++) {
33 free(argv[i]);
34 argv[i] = NULL;
35 }
36}
37} // namespace {}
38
39uint32 Subprocess::Exec(const std::vector<std::string>& cmd,
40 ExecCallback callback,
41 void *p) {
42 GPid child_pid;
43 GError *err;
44 scoped_array<char *> argv(new char*[cmd.size() + 1]);
45 for (unsigned int i = 0; i < cmd.size(); i++) {
46 argv[i] = strdup(cmd[i].c_str());
47 }
48 argv[cmd.size()] = NULL;
49 char *argp[1];
50 argp[0] = NULL;
51
52 SubprocessCallbackRecord callback_record;
53 callback_record.callback = callback;
54 callback_record.callback_data = p;
55
56 bool success = g_spawn_async(NULL, // working directory
57 argv.get(),
58 argp,
59 G_SPAWN_DO_NOT_REAP_CHILD, // flags
60 NULL, // child setup function
61 NULL, // child setup data pointer
62 &child_pid,
63 &err);
64 FreeArgv(argv.get());
65 if (!success) {
66 LOG(ERROR) << "g_spawn_async failed";
67 return 0;
68 }
69 guint *tag = new guint;
70 *tag = g_child_watch_add(child_pid, GChildExitedCallback, tag);
71 callback_records_[*tag] = callback_record;
72 return *tag;
73}
74
75void Subprocess::CancelExec(uint32 tag) {
76 if (callback_records_[tag].callback) {
77 callback_records_[tag].callback = NULL;
78 }
79}
80
81bool Subprocess::SynchronousExec(const std::vector<std::string>& cmd,
82 int* return_code) {
Andrew de los Reyesb10320d2010-03-31 16:44:44 -070083 GError *err = NULL;
adlr@google.com3defe6a2009-12-04 20:57:17 +000084 scoped_array<char *> argv(new char*[cmd.size() + 1]);
85 for (unsigned int i = 0; i < cmd.size(); i++) {
86 argv[i] = strdup(cmd[i].c_str());
87 }
88 argv[cmd.size()] = NULL;
89 char *argp[1];
90 argp[0] = NULL;
91
92 bool success = g_spawn_sync(NULL, // working directory
93 argv.get(),
94 argp,
95 static_cast<GSpawnFlags>(NULL), // flags
96 NULL, // child setup function
97 NULL, // data for child setup function
98 NULL, // return location for stdout
99 NULL, // return location for stderr
100 return_code,
101 &err);
102 FreeArgv(argv.get());
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700103 if (err)
104 LOG(INFO) << "err is: " << err->code << ", " << err->message;
adlr@google.com3defe6a2009-12-04 20:57:17 +0000105 return success;
106}
107
108Subprocess* Subprocess::subprocess_singleton_ = NULL;
109
110} // namespace chromeos_update_engine