shill: vpn: Implement a ProcessKiller singleton.
This class may be used to terminate and reap child processes
asynchronously and robustly. Also:
- Use ProcessKiller to kill spawned "openvpn" and "l2tpipsec_vpn"
processes.
- Delete the associated OpenVPN tunnel interfaces cleanly after the
openvpn process dies.
- Fix a somewhat harmless bug where shill was sending SIGTERM to
already dead VPN processes from child watch callbacks.
BUG=chromium-os:31535,chromium-os:31571
TEST=unit tests, tested on device
Change-Id: If15f08e76c51dac33a434551ef4ba11ca66d0401
Reviewed-on: https://gerrit.chromium.org/gerrit/24610
Tested-by: Darin Petkov <petkov@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Commit-Ready: Darin Petkov <petkov@chromium.org>
diff --git a/process_killer_unittest.cc b/process_killer_unittest.cc
new file mode 100644
index 0000000..477d9a4
--- /dev/null
+++ b/process_killer_unittest.cc
@@ -0,0 +1,48 @@
+// Copyright (c) 2012 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.
+
+#include "shill/process_killer.h"
+
+#include <base/bind.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using base::Bind;
+using base::Closure;
+using base::Unretained;
+
+namespace shill {
+
+class ProcessKillerTest : public testing::Test {
+ public:
+ ProcessKillerTest() : process_killer_(ProcessKiller::GetInstance()) {}
+
+ protected:
+ class Target {
+ public:
+ virtual ~Target() {}
+
+ MOCK_METHOD0(Call, void());
+ };
+
+ ProcessKiller *process_killer_;
+};
+
+TEST_F(ProcessKillerTest, OnProcessDied) {
+ const int kPID = 123;
+ EXPECT_TRUE(process_killer_->callbacks_.empty());
+ // Expect no crash.
+ ProcessKiller::OnProcessDied(kPID, 0, process_killer_);
+ process_killer_->callbacks_[kPID] = Closure();
+ // Expect no crash.
+ ProcessKiller::OnProcessDied(kPID, 0, process_killer_);
+ EXPECT_TRUE(process_killer_->callbacks_.empty());
+ Target target;
+ EXPECT_CALL(target, Call());
+ process_killer_->callbacks_[kPID] = Bind(&Target::Call, Unretained(&target));
+ ProcessKiller::OnProcessDied(kPID, 0, process_killer_);
+ EXPECT_TRUE(process_killer_->callbacks_.empty());
+}
+
+} // namespace shill