blob: 3492e79a250d82962b13a127938d9a20413f4e88 [file] [log] [blame]
Darin Petkov6f03a3b2010-11-10 14:27:14 -08001// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
adlr@google.com3defe6a2009-12-04 20:57:17 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_SUBPROCESS_H__
6#define CHROMEOS_PLATFORM_UPDATE_ENGINE_SUBPROCESS_H__
7
8#include <map>
9#include <string>
Darin Petkov6f03a3b2010-11-10 14:27:14 -080010#include <tr1/memory>
adlr@google.com3defe6a2009-12-04 20:57:17 +000011#include <vector>
Darin Petkov6f03a3b2010-11-10 14:27:14 -080012
adlr@google.com3defe6a2009-12-04 20:57:17 +000013#include <glib.h>
Darin Petkov6f03a3b2010-11-10 14:27:14 -080014
adlr@google.com3defe6a2009-12-04 20:57:17 +000015#include "base/basictypes.h"
Chris Masone790e62e2010-08-12 10:41:18 -070016#include "base/logging.h"
adlr@google.com3defe6a2009-12-04 20:57:17 +000017
18// The Subprocess class is a singleton. It's used to spawn off a subprocess
19// and get notified when the subprocess exits. The result of Exec() can
20// be saved and used to cancel the callback request. If you know you won't
21// call CancelExec(), you may safely lose the return value from Exec().
22
23namespace chromeos_update_engine {
24
25class Subprocess {
26 public:
Darin Petkov6f03a3b2010-11-10 14:27:14 -080027 typedef void(*ExecCallback)(int return_code,
28 const std::string& output,
29 void *p);
30
adlr@google.com3defe6a2009-12-04 20:57:17 +000031 static void Init() {
32 CHECK(!subprocess_singleton_);
33 subprocess_singleton_ = new Subprocess;
34 }
adlr@google.com3defe6a2009-12-04 20:57:17 +000035
36 // Returns a tag > 0 on success.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070037 uint32_t Exec(const std::vector<std::string>& cmd,
38 ExecCallback callback,
39 void* p);
adlr@google.com3defe6a2009-12-04 20:57:17 +000040
41 // Used to cancel the callback. The process will still run to completion.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070042 void CancelExec(uint32_t tag);
adlr@google.com3defe6a2009-12-04 20:57:17 +000043
44 // Executes a command synchronously. Returns true on success.
Andrew de los Reyes5a232832010-10-12 16:20:54 -070045 static bool SynchronousExecFlags(const std::vector<std::string>& cmd,
46 int* return_code,
47 GSpawnFlags flags);
adlr@google.com3defe6a2009-12-04 20:57:17 +000048 static bool SynchronousExec(const std::vector<std::string>& cmd,
Andrew de los Reyes5a232832010-10-12 16:20:54 -070049 int* return_code) {
50 return SynchronousExecFlags(cmd, return_code, static_cast<GSpawnFlags>(0));
51 }
adlr@google.com3defe6a2009-12-04 20:57:17 +000052
53 // Gets the one instance
54 static Subprocess& Get() {
55 return *subprocess_singleton_;
56 }
Darin Petkov6f03a3b2010-11-10 14:27:14 -080057
adlr@google.com3defe6a2009-12-04 20:57:17 +000058 // Returns true iff there is at least one subprocess we're waiting on.
Darin Petkov6f03a3b2010-11-10 14:27:14 -080059 bool SubprocessInFlight();
60
adlr@google.com3defe6a2009-12-04 20:57:17 +000061 private:
Darin Petkov6f03a3b2010-11-10 14:27:14 -080062 struct SubprocessRecord {
63 SubprocessRecord()
64 : tag(0),
65 callback(NULL),
66 callback_data(NULL),
67 gioout(NULL),
68 gioout_tag(0) {}
69 uint32_t tag;
70 ExecCallback callback;
71 void* callback_data;
72 GIOChannel* gioout;
73 guint gioout_tag;
74 std::string stdout;
75 };
76
77 Subprocess() {}
adlr@google.com3defe6a2009-12-04 20:57:17 +000078
79 // Callback for when any subprocess terminates. This calls the user
80 // requested callback.
81 static void GChildExitedCallback(GPid pid, gint status, gpointer data);
82
Kenneth Watersa7fcafa2010-09-21 10:27:03 -070083 // Callback which runs in the child before exec to redirect stderr onto
84 // stdout.
85 static void GRedirectStderrToStdout(gpointer user_data);
86
Darin Petkov6f03a3b2010-11-10 14:27:14 -080087 // Callback which runs whenever there is input available on the subprocess
88 // stdout pipe.
89 static gboolean GStdoutWatchCallback(GIOChannel* source,
90 GIOCondition condition,
91 gpointer data);
adlr@google.com3defe6a2009-12-04 20:57:17 +000092
Darin Petkov6f03a3b2010-11-10 14:27:14 -080093 // The global instance.
94 static Subprocess* subprocess_singleton_;
adlr@google.com3defe6a2009-12-04 20:57:17 +000095
Darin Petkov6f03a3b2010-11-10 14:27:14 -080096 // A map from the asynchronous subprocess tag (see Exec) to the subprocess
97 // record structure for all active asynchronous subprocesses.
98 std::map<int, std::tr1::shared_ptr<SubprocessRecord> > subprocess_records_;
99
adlr@google.com3defe6a2009-12-04 20:57:17 +0000100 DISALLOW_COPY_AND_ASSIGN(Subprocess);
101};
102
103} // namespace chromeos_update_engine
104
105#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_SUBPROCESS_H__