blob: bf1e7ea7ca4cfe3b17628236be8b9e04d4c2f0a6 [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#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_SUBPROCESS_H__
6#define CHROMEOS_PLATFORM_UPDATE_ENGINE_SUBPROCESS_H__
7
8#include <map>
9#include <string>
10#include <vector>
11#include <glib.h>
adlr@google.com3defe6a2009-12-04 20:57:17 +000012#include "base/basictypes.h"
Chris Masone790e62e2010-08-12 10:41:18 -070013#include "base/logging.h"
adlr@google.com3defe6a2009-12-04 20:57:17 +000014
15// The Subprocess class is a singleton. It's used to spawn off a subprocess
16// and get notified when the subprocess exits. The result of Exec() can
17// be saved and used to cancel the callback request. If you know you won't
18// call CancelExec(), you may safely lose the return value from Exec().
19
20namespace chromeos_update_engine {
21
22class Subprocess {
23 public:
24 static void Init() {
25 CHECK(!subprocess_singleton_);
26 subprocess_singleton_ = new Subprocess;
27 }
28
29 typedef void(*ExecCallback)(int return_code, void *p);
30
31 // Returns a tag > 0 on success.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070032 uint32_t Exec(const std::vector<std::string>& cmd,
33 ExecCallback callback,
34 void* p);
adlr@google.com3defe6a2009-12-04 20:57:17 +000035
36 // Used to cancel the callback. The process will still run to completion.
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070037 void CancelExec(uint32_t tag);
adlr@google.com3defe6a2009-12-04 20:57:17 +000038
39 // Executes a command synchronously. Returns true on success.
Andrew de los Reyes5a232832010-10-12 16:20:54 -070040 static bool SynchronousExecFlags(const std::vector<std::string>& cmd,
41 int* return_code,
42 GSpawnFlags flags);
adlr@google.com3defe6a2009-12-04 20:57:17 +000043 static bool SynchronousExec(const std::vector<std::string>& cmd,
Andrew de los Reyes5a232832010-10-12 16:20:54 -070044 int* return_code) {
45 return SynchronousExecFlags(cmd, return_code, static_cast<GSpawnFlags>(0));
46 }
adlr@google.com3defe6a2009-12-04 20:57:17 +000047
48 // Gets the one instance
49 static Subprocess& Get() {
50 return *subprocess_singleton_;
51 }
52
53 // Returns true iff there is at least one subprocess we're waiting on.
54 bool SubprocessInFlight() {
55 for (std::map<int, SubprocessCallbackRecord>::iterator it =
56 callback_records_.begin();
57 it != callback_records_.end(); ++it) {
58 if (it->second.callback)
59 return true;
60 }
61 return false;
62 }
63 private:
64 // The global instance
65 static Subprocess* subprocess_singleton_;
66
67 // Callback for when any subprocess terminates. This calls the user
68 // requested callback.
69 static void GChildExitedCallback(GPid pid, gint status, gpointer data);
70
Kenneth Watersa7fcafa2010-09-21 10:27:03 -070071 // Callback which runs in the child before exec to redirect stderr onto
72 // stdout.
73 static void GRedirectStderrToStdout(gpointer user_data);
74
adlr@google.com3defe6a2009-12-04 20:57:17 +000075 struct SubprocessCallbackRecord {
76 ExecCallback callback;
77 void* callback_data;
78 };
79
80 std::map<int, SubprocessCallbackRecord> callback_records_;
81
82 Subprocess() {}
83 DISALLOW_COPY_AND_ASSIGN(Subprocess);
84};
85
86} // namespace chromeos_update_engine
87
88#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_SUBPROCESS_H__