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