logging_CrashSender: rework to handle new locking system

The crash_sender logic uses flock now to guarantee locking between runs
rather than the old pid file management.  Update the autotests to handle
that method so we can delete the old pid heuristic.

BUG=chromium:199491
TEST=`cbuildbot x86-generic-full` works
CQ-DEPEND=CL:169486

Change-Id: I563b619d44cc2c426807fcedd24332a3c14acccf
Reviewed-on: https://chromium-review.googlesource.com/201495
Reviewed-by: Ben Chan <benchan@chromium.org>
Tested-by: Mike Frysinger <vapier@chromium.org>
Commit-Queue: Mike Frysinger <vapier@chromium.org>
diff --git a/client/cros/crash_test.py b/client/cros/crash_test.py
index fe4c75e..e7a314c 100644
--- a/client/cros/crash_test.py
+++ b/client/cros/crash_test.py
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import logging, os, re, shutil
+import contextlib, fcntl, logging, os, re, shutil
 
 import common, cros_logging
 from autotest_lib.client.bin import test, utils
@@ -74,6 +74,7 @@
     _CRASH_SENDER_PATH = '/sbin/crash_sender'
     _CRASH_SENDER_RATE_DIR = '/var/lib/crash_sender'
     _CRASH_SENDER_RUN_PATH = '/var/run/crash_sender.pid'
+    _CRASH_SENDER_LOCK_PATH = '/var/lock/crash_sender'
     _CRASH_TEST_IN_PROGRESS = '/tmp/crash-test-in-progress'
     _MOCK_CRASH_SENDING = '/tmp/mock-crash-sending'
     _PAUSE_FILE = '/var/lib/crash_sender_paused'
@@ -612,6 +613,17 @@
         self._replace_crash_reporter_filter_in('')
 
 
+    @contextlib.contextmanager
+    def hold_crash_lock(self):
+        """A context manager to hold the crash sender lock."""
+        with open(self._CRASH_SENDER_LOCK_PATH, 'w+') as f:
+            fcntl.flock(f.fileno(), fcntl.LOCK_EX)
+            try:
+                yield
+            finally:
+                fcntl.flock(f.fileno(), fcntl.LOCK_UN)
+
+
     def initialize(self):
         """Initalize the test."""
         test.test.initialize(self)
diff --git a/client/site_tests/logging_CrashSender/logging_CrashSender.py b/client/site_tests/logging_CrashSender/logging_CrashSender.py
index 284a6c4..aa38550 100644
--- a/client/site_tests/logging_CrashSender/logging_CrashSender.py
+++ b/client/site_tests/logging_CrashSender/logging_CrashSender.py
@@ -183,17 +183,12 @@
 
 
     def _test_sender_single_instance(self):
-        """Test the sender fails to start when another instance is running.
-
-        Here we rely on the sender not checking the other running pid
-        is of the same instance.
-        """
-        utils.open_write_close(self._CRASH_SENDER_RUN_PATH, str(os.getpid()))
-        result = self._call_sender_one_crash()
-        if (not 'Already running.' in result['output'] or
-            result['send_attempt'] or not result['report_exists']):
-            raise error.TestFail('Allowed multiple instances to run')
-        os.remove(self._CRASH_SENDER_RUN_PATH)
+        """Test the sender fails to start when another instance is running."""
+        with self.hold_crash_lock():
+            result = self._call_sender_one_crash()
+            if (not 'Already running; quitting.' in result['output'] or
+                result['send_attempt'] or not result['report_exists']):
+                raise error.TestFail('Allowed multiple instances to run')
 
 
     def _test_sender_send_fails(self):