blob: 8fdf60f66e6aaec0b4010d4097f3909523e54afb [file] [log] [blame]
mukesh agrawalae30e9e2013-05-28 14:09:16 -07001// Copyright (c) 2013 The Chromium OS 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 SHILL_EXTERNAL_TASK_H_
6#define SHILL_EXTERNAL_TASK_H_
7
8#include <sys/types.h>
9
10#include <map>
Ben Chancd477322014-10-17 14:19:30 -070011#include <memory>
mukesh agrawalae30e9e2013-05-28 14:09:16 -070012#include <string>
13#include <vector>
14
15#include <base/callback.h>
Ben Chana0ddf462014-02-06 11:32:42 -080016#include <base/files/file_path.h>
mukesh agrawalae30e9e2013-05-28 14:09:16 -070017#include <base/memory/weak_ptr.h>
18#include <gtest/gtest_prod.h> // for FRIEND_TEST
19
20#include "shill/glib.h"
21#include "shill/rpc_task.h"
22
23namespace shill {
24
25class ControlInterface;
26class Error;
mukesh agrawal9da07772013-05-15 14:15:17 -070027class EventDispatcher;
mukesh agrawalae30e9e2013-05-28 14:09:16 -070028class ProcessKiller;
29
30class ExternalTask : public RPCTaskDelegate {
31 public:
Paul Stewarta794cd62015-06-16 13:13:10 -070032 ExternalTask(ControlInterface* control,
33 GLib* glib,
34 const base::WeakPtr<RPCTaskDelegate>& task_delegate,
35 const base::Callback<void(pid_t, int)>& death_callback);
Ben Chan5ea763b2014-08-13 11:07:54 -070036 ~ExternalTask() override; // But consider DestroyLater...
mukesh agrawal9da07772013-05-15 14:15:17 -070037
38 // Schedule later deletion of the ExternalTask. Useful when in the
39 // middle of an ExternalTask callback. Note that the caller _must_
40 // release ownership of |this|. For example:
41 //
42 // class Foo : public SupportsWeakPtr<Foo>, public RPCTaskDelegate {
43 // public:
44 // Foo() {
45 // task_.reset(new ExternalTask(...));
46 // }
47 //
48 // void Notify(...) {
49 // task_.release()->DestroyLater(...); // Passes ownership.
50 // }
51 //
52 // private:
Ben Chancd477322014-10-17 14:19:30 -070053 // std::unique_ptr<ExternalTask> task_;
mukesh agrawal9da07772013-05-15 14:15:17 -070054 // }
Paul Stewarta794cd62015-06-16 13:13:10 -070055 void DestroyLater(EventDispatcher* dispatcher);
mukesh agrawalae30e9e2013-05-28 14:09:16 -070056
57 // Forks off a process to run |program|, with the command-line
58 // arguments |arguments|, and the environment variables specified in
59 // |environment|.
60 //
mukesh agrawalc4f9aa02013-08-15 19:23:13 -070061 // If |terminate_with_parent| is true, the child process will be
62 // configured to terminate itself if this process dies. Otherwise,
63 // the child process will retain its default behavior.
64 //
mukesh agrawalae30e9e2013-05-28 14:09:16 -070065 // On success, returns true, and leaves |error| unmodified.
66 // On failure, returns false, and sets |error|.
67 //
68 // |environment| SHOULD NOT contain kRPCTaskServiceVariable or
69 // kRPCTaskPathVariable, as that may prevent the child process
70 // from communicating back to the ExternalTask.
Paul Stewarta794cd62015-06-16 13:13:10 -070071 virtual bool Start(const base::FilePath& program,
72 const std::vector<std::string>& arguments,
73 const std::map<std::string, std::string>& environment,
mukesh agrawalc4f9aa02013-08-15 19:23:13 -070074 bool terminate_with_parent,
Paul Stewarta794cd62015-06-16 13:13:10 -070075 Error* error);
mukesh agrawalae30e9e2013-05-28 14:09:16 -070076 virtual void Stop();
77
78 private:
79 friend class ExternalTaskTest;
80 FRIEND_TEST(ExternalTaskTest, Destructor);
81 FRIEND_TEST(ExternalTaskTest, GetLogin);
82 FRIEND_TEST(ExternalTaskTest, Notify);
83 FRIEND_TEST(ExternalTaskTest, OnTaskDied);
84 FRIEND_TEST(ExternalTaskTest, Start);
85 FRIEND_TEST(ExternalTaskTest, Stop);
86 FRIEND_TEST(ExternalTaskTest, StopNotStarted);
87
88 // Implements RPCTaskDelegate.
Paul Stewarta794cd62015-06-16 13:13:10 -070089 void GetLogin(std::string* user, std::string* password) override;
Alex Vakulenko016fa0e2014-08-11 15:59:58 -070090 void Notify(
Paul Stewarta794cd62015-06-16 13:13:10 -070091 const std::string& event,
92 const std::map<std::string, std::string>& details) override;
mukesh agrawalae30e9e2013-05-28 14:09:16 -070093 // Called when the external process exits.
94 static void OnTaskDied(GPid pid, gint status, gpointer data);
95
Paul Stewarta794cd62015-06-16 13:13:10 -070096 static void Destroy(ExternalTask* task);
mukesh agrawal9da07772013-05-15 14:15:17 -070097
mukesh agrawalc4f9aa02013-08-15 19:23:13 -070098 // This method is run in the child process (i.e. after fork(), but
99 // before exec()). It configures the child to receive a SIGTERM when
100 // the parent exits.
101 static void SetupTermination(gpointer glib_user_data);
102
Paul Stewarta794cd62015-06-16 13:13:10 -0700103 ControlInterface* control_;
104 GLib* glib_;
105 ProcessKiller* process_killer_; // Field permits mocking.
mukesh agrawalae30e9e2013-05-28 14:09:16 -0700106
Ben Chancd477322014-10-17 14:19:30 -0700107 std::unique_ptr<RPCTask> rpc_task_;
mukesh agrawalae30e9e2013-05-28 14:09:16 -0700108 base::WeakPtr<RPCTaskDelegate> task_delegate_;
109 base::Callback<void(pid_t, int)> death_callback_;
110
111 // The PID of the spawned process. May be 0 if no process has been
112 // spawned yet or the process has died.
113 pid_t pid_;
114
115 // Child exit watch callback source tag.
116 unsigned int child_watch_tag_;
117
118 DISALLOW_COPY_AND_ASSIGN(ExternalTask);
119};
120
121} // namespace shill
122
123#endif // SHILL_EXTERNAL_TASK_H_