AU: Execute postinst asynchronously so that the D-Bus service is not blocked.
This CL also cleans up Subprocess memory handling a bit and extends it to
capture the output of asynchronous subprocesses. Also adds a scoped temp mount
unmounter utility class.
BUG=8937
TEST=unit tests, tested on the device -- making sure no D-Bus calls timeou
during postinstall.
Change-Id: I219dda3dc98d875ff05050f1a32ffcc925db1d53
Review URL: http://codereview.chromium.org/4690006
diff --git a/subprocess.h b/subprocess.h
index bf1e7ea..3492e79 100644
--- a/subprocess.h
+++ b/subprocess.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -7,8 +7,11 @@
#include <map>
#include <string>
+#include <tr1/memory>
#include <vector>
+
#include <glib.h>
+
#include "base/basictypes.h"
#include "base/logging.h"
@@ -21,12 +24,14 @@
class Subprocess {
public:
+ typedef void(*ExecCallback)(int return_code,
+ const std::string& output,
+ void *p);
+
static void Init() {
CHECK(!subprocess_singleton_);
subprocess_singleton_ = new Subprocess;
}
-
- typedef void(*ExecCallback)(int return_code, void *p);
// Returns a tag > 0 on success.
uint32_t Exec(const std::vector<std::string>& cmd,
@@ -49,20 +54,27 @@
static Subprocess& Get() {
return *subprocess_singleton_;
}
-
+
// Returns true iff there is at least one subprocess we're waiting on.
- bool SubprocessInFlight() {
- for (std::map<int, SubprocessCallbackRecord>::iterator it =
- callback_records_.begin();
- it != callback_records_.end(); ++it) {
- if (it->second.callback)
- return true;
- }
- return false;
- }
+ bool SubprocessInFlight();
+
private:
- // The global instance
- static Subprocess* subprocess_singleton_;
+ struct SubprocessRecord {
+ SubprocessRecord()
+ : tag(0),
+ callback(NULL),
+ callback_data(NULL),
+ gioout(NULL),
+ gioout_tag(0) {}
+ uint32_t tag;
+ ExecCallback callback;
+ void* callback_data;
+ GIOChannel* gioout;
+ guint gioout_tag;
+ std::string stdout;
+ };
+
+ Subprocess() {}
// Callback for when any subprocess terminates. This calls the user
// requested callback.
@@ -72,14 +84,19 @@
// stdout.
static void GRedirectStderrToStdout(gpointer user_data);
- struct SubprocessCallbackRecord {
- ExecCallback callback;
- void* callback_data;
- };
+ // Callback which runs whenever there is input available on the subprocess
+ // stdout pipe.
+ static gboolean GStdoutWatchCallback(GIOChannel* source,
+ GIOCondition condition,
+ gpointer data);
- std::map<int, SubprocessCallbackRecord> callback_records_;
+ // The global instance.
+ static Subprocess* subprocess_singleton_;
- Subprocess() {}
+ // A map from the asynchronous subprocess tag (see Exec) to the subprocess
+ // record structure for all active asynchronous subprocesses.
+ std::map<int, std::tr1::shared_ptr<SubprocessRecord> > subprocess_records_;
+
DISALLOW_COPY_AND_ASSIGN(Subprocess);
};