Update the logic to force cleanup all edit monitor instances.

Instead of checking the pidfiles, query all the running process with
binary ends with "edit_monitor" and kill all of those processes. This
ensures that if there are any unexpected edit monitor instances running
(e.g. due to b/382135550), the force cleanup can kill those processes as
well.

Bug: 382135550
Test: atest daemon_manager_test
Change-Id: I299f16b7b913e4ee470b5fe9ef0ffdad8d3c0945
diff --git a/tools/edit_monitor/daemon_manager.py b/tools/edit_monitor/daemon_manager.py
index a352e30..36a7593 100644
--- a/tools/edit_monitor/daemon_manager.py
+++ b/tools/edit_monitor/daemon_manager.py
@@ -413,13 +413,19 @@
   def _find_all_instances_pids(self) -> list[int]:
     pids = []
 
-    for file in os.listdir(self.pid_file_path.parent):
-      if file.endswith(".lock"):
-        try:
-          with open(self.pid_file_path.parent.joinpath(file), "r") as f:
-            pids.append(int(f.read().strip()))
-        except (FileNotFoundError, IOError, ValueError, TypeError):
-          logging.exception("Failed to get pid from file path: %s", file)
+    try:
+      output = subprocess.check_output(
+          ["ps", "-ef", "--no-headers"], text=True)
+      for line in output.splitlines():
+          parts = line.split()
+          process_path = parts[7]
+          if pathlib.Path(process_path).name == 'edit_monitor':
+            pid = int(parts[1])
+            if pid != self.pid:  # exclude the current process
+              pids.append(pid)
+    except Exception:
+      logging.exception(
+          "Failed to get pids of existing edit monitors from ps command.")
 
     return pids
 
diff --git a/tools/edit_monitor/daemon_manager_test.py b/tools/edit_monitor/daemon_manager_test.py
index 350739d..e412ab0 100644
--- a/tools/edit_monitor/daemon_manager_test.py
+++ b/tools/edit_monitor/daemon_manager_test.py
@@ -367,6 +367,26 @@
         fake_cclient, edit_event_pb2.EditEvent.FAILED_TO_REBOOT_EDIT_MONITOR
     )
 
+  @mock.patch('subprocess.check_output')
+  def test_cleanup_success(self, mock_check_output):
+    p = self._create_fake_deamon_process()
+    fake_cclient = FakeClearcutClient()
+    mock_check_output.return_value = f'user {p.pid} 1 1 1 1 1 edit_monitor arg'
+
+    dm = daemon_manager.DaemonManager(
+        TEST_BINARY_FILE,
+        daemon_target=long_running_daemon,
+        cclient=fake_cclient,
+    )
+    dm.cleanup()
+
+    self.assertFalse(p.is_alive())
+    self.assertTrue(
+        pathlib.Path(self.working_dir.name)
+        .joinpath(daemon_manager.BLOCK_SIGN_FILE)
+        .exists()
+    )
+
   def assert_run_simple_daemon_success(self):
     damone_output_file = tempfile.NamedTemporaryFile(
         dir=self.working_dir.name, delete=False
diff --git a/tools/edit_monitor/main.py b/tools/edit_monitor/main.py
index 7ca0daa..3c2d183 100644
--- a/tools/edit_monitor/main.py
+++ b/tools/edit_monitor/main.py
@@ -102,12 +102,12 @@
       daemon_args=(args.path, args.dry_run),
   )
 
-  if args.force_cleanup:
-    dm.cleanup()
-
   try:
-    dm.start()
-    dm.monitor_daemon()
+    if args.force_cleanup:
+      dm.cleanup()
+    else:
+      dm.start()
+      dm.monitor_daemon()
   except Exception:
     logging.exception('Unexpected exception raised when run daemon.')
   finally: