| // Copyright (c) 2013 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. |
| |
| #ifndef SHILL_EXTERNAL_TASK_H_ |
| #define SHILL_EXTERNAL_TASK_H_ |
| |
| #include <sys/types.h> |
| |
| #include <map> |
| #include <string> |
| #include <vector> |
| |
| #include <base/callback.h> |
| #include <base/files/file_path.h> |
| #include <base/memory/scoped_ptr.h> |
| #include <base/memory/weak_ptr.h> |
| #include <gtest/gtest_prod.h> // for FRIEND_TEST |
| |
| #include "shill/glib.h" |
| #include "shill/rpc_task.h" |
| |
| namespace shill { |
| |
| class ControlInterface; |
| class Error; |
| class EventDispatcher; |
| class ProcessKiller; |
| |
| class ExternalTask : public RPCTaskDelegate { |
| public: |
| ExternalTask(ControlInterface *control, |
| GLib *glib, |
| const base::WeakPtr<RPCTaskDelegate> &task_delegate, |
| const base::Callback<void(pid_t, int)> &death_callback); |
| ~ExternalTask() override; // But consider DestroyLater... |
| |
| // Schedule later deletion of the ExternalTask. Useful when in the |
| // middle of an ExternalTask callback. Note that the caller _must_ |
| // release ownership of |this|. For example: |
| // |
| // class Foo : public SupportsWeakPtr<Foo>, public RPCTaskDelegate { |
| // public: |
| // Foo() { |
| // task_.reset(new ExternalTask(...)); |
| // } |
| // |
| // void Notify(...) { |
| // task_.release()->DestroyLater(...); // Passes ownership. |
| // } |
| // |
| // private: |
| // scoped_ptr<ExternalTask> task_; |
| // } |
| void DestroyLater(EventDispatcher *dispatcher); |
| |
| // Forks off a process to run |program|, with the command-line |
| // arguments |arguments|, and the environment variables specified in |
| // |environment|. |
| // |
| // If |terminate_with_parent| is true, the child process will be |
| // configured to terminate itself if this process dies. Otherwise, |
| // the child process will retain its default behavior. |
| // |
| // On success, returns true, and leaves |error| unmodified. |
| // On failure, returns false, and sets |error|. |
| // |
| // |environment| SHOULD NOT contain kRPCTaskServiceVariable or |
| // kRPCTaskPathVariable, as that may prevent the child process |
| // from communicating back to the ExternalTask. |
| virtual bool Start(const base::FilePath &program, |
| const std::vector<std::string> &arguments, |
| const std::map<std::string, std::string> &environment, |
| bool terminate_with_parent, |
| Error *error); |
| virtual void Stop(); |
| |
| private: |
| friend class ExternalTaskTest; |
| FRIEND_TEST(ExternalTaskTest, Destructor); |
| FRIEND_TEST(ExternalTaskTest, GetLogin); |
| FRIEND_TEST(ExternalTaskTest, Notify); |
| FRIEND_TEST(ExternalTaskTest, OnTaskDied); |
| FRIEND_TEST(ExternalTaskTest, Start); |
| FRIEND_TEST(ExternalTaskTest, Stop); |
| FRIEND_TEST(ExternalTaskTest, StopNotStarted); |
| |
| // Implements RPCTaskDelegate. |
| void GetLogin(std::string *user, std::string *password) override; |
| void Notify( |
| const std::string &event, |
| const std::map<std::string, std::string> &details) override; |
| // Called when the external process exits. |
| static void OnTaskDied(GPid pid, gint status, gpointer data); |
| |
| static void Destroy(ExternalTask *task); |
| |
| // This method is run in the child process (i.e. after fork(), but |
| // before exec()). It configures the child to receive a SIGTERM when |
| // the parent exits. |
| static void SetupTermination(gpointer glib_user_data); |
| |
| ControlInterface *control_; |
| GLib *glib_; |
| ProcessKiller *process_killer_; // Field permits mocking. |
| |
| scoped_ptr<RPCTask> rpc_task_; |
| base::WeakPtr<RPCTaskDelegate> task_delegate_; |
| base::Callback<void(pid_t, int)> death_callback_; |
| |
| // The PID of the spawned process. May be 0 if no process has been |
| // spawned yet or the process has died. |
| pid_t pid_; |
| |
| // Child exit watch callback source tag. |
| unsigned int child_watch_tag_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ExternalTask); |
| }; |
| |
| } // namespace shill |
| |
| #endif // SHILL_EXTERNAL_TASK_H_ |