mod.rs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. use nix::sys::wait::{WaitPidFlag, WaitStatus};
  2. use tokio::signal::unix::{signal, SignalKind, Signal};
  3. use crate::logger::LogWriter;
  4. use std::sync::atomic::{AtomicU64, Ordering};
  5. use lazy_static::lazy_static;
  6. lazy_static!{
  7. static ref REAP_COUNTER: AtomicU64 = AtomicU64::new(0);
  8. }
  9. pub struct Reaper {
  10. sig_stream: Signal,
  11. logger: LogWriter,
  12. }
  13. impl Reaper {
  14. pub fn new(logger: LogWriter) -> Result<Self, std::io::Error> {
  15. let stream = signal(SignalKind::child())?;
  16. Ok(Reaper { sig_stream: stream, logger })
  17. }
  18. pub async fn reap(&mut self) -> ! {
  19. loop {
  20. self.sig_stream.recv().await;
  21. loop {
  22. let wstat = nix::sys::wait::waitpid(nix::unistd::Pid::from_raw(-1), Some(WaitPidFlag::WNOHANG));
  23. match wstat {
  24. Ok(ws) => {
  25. if LogWriter::is_debug_mode() {
  26. let msg = match ws {
  27. WaitStatus::Exited(pid, ec) => {
  28. Some(format!("{}: WIFEXITED ExitCode={}", pid, ec))
  29. }
  30. WaitStatus::Signaled(pid, sig, t) => {
  31. Some(format!("{}: WIFSIGNALED Signal={}, IsCoreDump={}", pid, sig, t))
  32. }
  33. WaitStatus::Stopped(pid, c) => {
  34. Some(format!("{}: WIFSTOPPED Code={}", pid, c))
  35. }
  36. WaitStatus::PtraceEvent(pid, sig, c) => {
  37. Some(format!("{}: PTRACE_EVENT Signal={}, Value={}", pid, sig, c))
  38. }
  39. WaitStatus::PtraceSyscall(pid) => {
  40. Some(format!("{}: PTRACE_SYSCALL", pid))
  41. }
  42. WaitStatus::Continued(pid) => {
  43. Some(format!("{}: WCONTINUED", pid))
  44. }
  45. WaitStatus::StillAlive => {
  46. None
  47. }
  48. };
  49. if let Some(v) = msg {
  50. REAP_COUNTER.fetch_add(1, Ordering::Relaxed);
  51. self.logger.error(format!("reap zombie child {}", v).as_str()).await;
  52. }
  53. }else{
  54. if ws != WaitStatus::StillAlive {
  55. REAP_COUNTER.fetch_add(1, Ordering::Relaxed);
  56. }
  57. }
  58. }
  59. Err(_) => {}
  60. };
  61. }
  62. };
  63. }
  64. }
  65. pub fn get_count() -> u64 {
  66. REAP_COUNTER.load(Ordering::Relaxed)
  67. }