From 8974d82867d2ebc5fef178514eae7422b8a5fa47 Mon Sep 17 00:00:00 2001
From: l00346806 <lixiaoguang2@huawei.com>
Date: Thu, 8 Sep 2022 22:07:27 +0800
Subject: [PATCH 4/4] fix start and stop repeatly, if the unit is already in
 process, just return before do action.

Signed-off-by: Xiaoguang Li <lixiaoguang2@huawei.com>
---
 components/service/src/service_mng.rs         | 40 ++++++++++++++-----
 components/service/src/service_pid.rs         | 14 +++++++
 components/service/src/service_unit.rs        |  6 ++-
 components/socket/src/socket_mng.rs           | 12 +++---
 components/socket/src/socket_unit.rs          | 15 ++++++-
 .../src/manager/unit/unit_entry/u_entry.rs    | 10 +++++
 6 files changed, 77 insertions(+), 20 deletions(-)

diff --git a/components/service/src/service_mng.rs b/components/service/src/service_mng.rs
index b8ac9f2..f11c23c 100755
--- a/components/service/src/service_mng.rs
+++ b/components/service/src/service_mng.rs
@@ -115,7 +115,7 @@ impl ServiceMng {
         }
     }
 
-    pub(super) fn start_check(&self) -> Result<(), UnitActionError> {
+    pub(super) fn start_check(&self) -> Result<bool, UnitActionError> {
         if IN_SET!(
             self.state(),
             ServiceState::Stop,
@@ -131,7 +131,18 @@ impl ServiceMng {
             return Err(UnitActionError::UnitActionEAgain);
         }
 
-        Ok(())
+        // service is in starting
+        if IN_SET!(
+            self.state(),
+            ServiceState::Condition,
+            ServiceState::StartPre,
+            ServiceState::Start,
+            ServiceState::StartPost
+        ) {
+            return Ok(true);
+        }
+
+        Ok(false)
     }
 
     pub(super) fn start_action(&self) {
@@ -140,15 +151,16 @@ impl ServiceMng {
     }
 
     pub(super) fn stop_check(&self) -> Result<(), UnitActionError> {
-        let stop_state = vec![
+        if IN_SET!(
+            self.state(),
             ServiceState::Stop,
             ServiceState::StopSigterm,
             ServiceState::StopSigkill,
             ServiceState::StopPost,
-        ];
-
-        if stop_state.contains(&self.state()) {
-            return Err(UnitActionError::UnitActionEAlready);
+            ServiceState::FinalSigterm,
+            ServiceState::FinalSigkill
+        ) {
+            return Ok(());
         }
 
         Ok(())
@@ -306,7 +318,11 @@ impl ServiceMng {
         if self.result() != ServiceResult::Success {
             self.enter_signal(ServiceState::StopSigterm, sr);
         } else if self.service_alive() {
-            self.set_state(ServiceState::Runing);
+            if self.rd.notify_state() == NotifyState::Stoping {
+                self.enter_stop_by_notify();
+            } else {
+                self.set_state(ServiceState::Runing);
+            }
         } else if let Some(remain_after_exit) =
             self.config.config_data().borrow().Service.RemainAfterExit
         {
@@ -514,8 +530,11 @@ impl ServiceMng {
     }
 
     fn service_alive(&self) -> bool {
-        // todo!()
-        true
+        if let Ok(v) = self.pid.main_alive() {
+            return v;
+        }
+
+        self.cgroup_good()
     }
 
     fn run_next_control(&self) {
@@ -660,7 +679,6 @@ impl ServiceMng {
                 msg: "main pid is not alive",
             });
         }
-
         if self
             .comm
             .um()
diff --git a/components/service/src/service_pid.rs b/components/service/src/service_pid.rs
index b976c5e..b2841ef 100755
--- a/components/service/src/service_pid.rs
+++ b/components/service/src/service_pid.rs
@@ -1,7 +1,9 @@
 use super::service_comm::ServiceComm;
 use nix::unistd::Pid;
+use process1::manager::UnitActionError;
 use std::cell::RefCell;
 use std::rc::Rc;
+use utils::process_util;
 
 pub(super) struct ServicePid {
     comm: Rc<ServiceComm>,
@@ -59,6 +61,10 @@ impl ServicePid {
     pub(super) fn control(&self) -> Option<Pid> {
         self.data.borrow().control()
     }
+
+    pub(super) fn main_alive(&self) -> Result<bool, UnitActionError> {
+        self.data.borrow().main_alive()
+    }
 }
 
 struct ServicePidData {
@@ -98,4 +104,12 @@ impl ServicePidData {
     pub(self) fn control(&self) -> Option<Pid> {
         self.control.as_ref().cloned()
     }
+
+    pub(self) fn main_alive(&self) -> Result<bool, UnitActionError> {
+        if self.main.is_none() {
+            return Err(UnitActionError::UnitActionEAgain);
+        }
+
+        Ok(process_util::alive(self.main.unwrap()))
+    }
 }
diff --git a/components/service/src/service_unit.rs b/components/service/src/service_unit.rs
index d9826f8..9ab1679 100755
--- a/components/service/src/service_unit.rs
+++ b/components/service/src/service_unit.rs
@@ -55,7 +55,11 @@ impl UnitObj for ServiceUnit {
 
     fn start(&self) -> Result<(), UnitActionError> {
         log::debug!("begin to start the service unit");
-        self.mng.start_check()?;
+        let started = self.mng.start_check()?;
+        if started {
+            log::debug!("service already in starting, just return immediately");
+            return Ok(());
+        }
 
         self.monitor.start_action();
         self.mng.start_action();
diff --git a/components/socket/src/socket_mng.rs b/components/socket/src/socket_mng.rs
index 9cca6f3..596fc12 100644
--- a/components/socket/src/socket_mng.rs
+++ b/components/socket/src/socket_mng.rs
@@ -150,7 +150,7 @@ impl SocketMng {
             .map_or(None, |v| Some(v.to_string()))
     }
 
-    pub(super) fn start_check(&self) -> Result<(), UnitActionError> {
+    pub(super) fn start_check(&self) -> Result<bool, UnitActionError> {
         if IN_SET!(
             self.state(),
             SocketState::StopPre,
@@ -170,7 +170,7 @@ impl SocketMng {
             SocketState::StartChown,
             SocketState::StartPost
         ) {
-            return Ok(());
+            return Ok(true);
         }
 
         self.unit_ref_target()
@@ -179,7 +179,7 @@ impl SocketMng {
                 Err(e) => Err(e),
             })?;
 
-        Ok(())
+        Ok(false)
     }
 
     pub(super) fn start_action(&self) {
@@ -190,7 +190,7 @@ impl SocketMng {
         self.enter_stop_pre(SocketResult::Success)
     }
 
-    pub(super) fn stop_check(&self) -> Result<(), UnitActionError> {
+    pub(super) fn stop_check(&self) -> Result<bool, UnitActionError> {
         if IN_SET!(
             self.state(),
             SocketState::StopPre,
@@ -200,7 +200,7 @@ impl SocketMng {
             SocketState::FinalSigterm,
             SocketState::FinalSigkill
         ) {
-            return Ok(());
+            return Ok(true);
         }
 
         if IN_SET!(
@@ -213,7 +213,7 @@ impl SocketMng {
             return Err(UnitActionError::UnitActionEAgain);
         }
 
-        Ok(())
+        Ok(false)
     }
 
     pub(super) fn current_active_state(&self) -> UnitActiveState {
diff --git a/components/socket/src/socket_unit.rs b/components/socket/src/socket_unit.rs
index 0e25ed0..2db7154 100644
--- a/components/socket/src/socket_unit.rs
+++ b/components/socket/src/socket_unit.rs
@@ -53,7 +53,13 @@ impl UnitObj for SocketUnit {
     // the function entrance to start the unit
     fn start(&self) -> Result<(), UnitActionError> {
         self.ports.attach(self.mng.clone());
-        self.mng.start_check()?;
+
+        let starting = self.mng.start_check()?;
+        if starting {
+            log::debug!("socket already in start");
+            return Ok(());
+        }
+
         self.mng.start_action();
 
         Ok(())
@@ -64,7 +70,12 @@ impl UnitObj for SocketUnit {
     }
 
     fn stop(&self) -> Result<(), UnitActionError> {
-        self.mng.stop_check()?;
+        let stoping = self.mng.stop_check()?;
+        if stoping {
+            log::debug!("socket already in stop, return immediretly");
+            return Ok(());
+        }
+
         self.mng.stop_action();
 
         Ok(())
diff --git a/process1/src/manager/unit/unit_entry/u_entry.rs b/process1/src/manager/unit/unit_entry/u_entry.rs
index 904ade1..9653dd8 100644
--- a/process1/src/manager/unit/unit_entry/u_entry.rs
+++ b/process1/src/manager/unit/unit_entry/u_entry.rs
@@ -458,6 +458,16 @@ impl Unit {
     }
 
     pub(super) fn stop(&self) -> Result<(), UnitActionError> {
+        let active_state = self.current_active_state();
+        let inactive_or_failed = match active_state {
+            UnitActiveState::UnitInActive | UnitActiveState::UnitFailed => true,
+            _ => false,
+        };
+
+        if inactive_or_failed {
+            return Err(UnitActionError::UnitActionEAlready);
+        }
+
         self.sub.stop()
     }
 
-- 
2.30.2

