/src/notification_handler.rs

https://github.com/KillingSpark/rustysd · Rust · 277 lines · 242 code · 25 blank · 10 comment · 32 complexity · 69815ba2b23c249009f08f7b28a89410 MD5 · raw file

  1. //! collect the different streams from the services
  2. //! Stdout and stderr get redirected to the normal stdout/err but are prefixed with a unique string to identify their output
  3. //! streams from the notification sockets get parsed and applied to the respective service
  4. use crate::platform::reset_event_fd;
  5. use crate::runtime_info::*;
  6. use crate::services::Service;
  7. use crate::services::StdIo;
  8. use crate::units::*;
  9. use std::{collections::HashMap, os::unix::io::AsRawFd};
  10. fn collect_from_srvc<F>(run_info: ArcMutRuntimeInfo, f: F) -> HashMap<i32, UnitId>
  11. where
  12. F: Fn(&mut HashMap<i32, UnitId>, &Service, UnitId),
  13. {
  14. let run_info_locked = run_info.read().unwrap();
  15. let unit_table = &run_info_locked.unit_table;
  16. unit_table
  17. .iter()
  18. .fold(HashMap::new(), |mut map, (id, srvc_unit)| {
  19. if let Specific::Service(srvc) = &srvc_unit.specific {
  20. let state = &*srvc.state.read().unwrap();
  21. f(&mut map, &state.srvc, id.clone());
  22. }
  23. map
  24. })
  25. }
  26. pub fn handle_all_streams(run_info: ArcMutRuntimeInfo) {
  27. let eventfd = { run_info.read().unwrap().notification_eventfd };
  28. loop {
  29. // need to collect all again. There might be a newly started service
  30. let fd_to_srvc_id = collect_from_srvc(run_info.clone(), |map, srvc, id| {
  31. if let Some(socket) = &srvc.notifications {
  32. map.insert(socket.as_raw_fd(), id);
  33. }
  34. });
  35. let mut fdset = nix::sys::select::FdSet::new();
  36. for fd in fd_to_srvc_id.keys() {
  37. fdset.insert(*fd);
  38. }
  39. fdset.insert(eventfd.read_end());
  40. let result = nix::sys::select::select(None, Some(&mut fdset), None, None, None);
  41. let run_info_locked = run_info.read().unwrap();
  42. let unit_table = &run_info_locked.unit_table;
  43. match result {
  44. Ok(_) => {
  45. if fdset.contains(eventfd.read_end()) {
  46. trace!("Interrupted notification select because the eventfd fired");
  47. reset_event_fd(eventfd);
  48. trace!("Reset eventfd value");
  49. }
  50. let mut buf = [0u8; 512];
  51. for (fd, id) in &fd_to_srvc_id {
  52. if fdset.contains(*fd) {
  53. if let Some(srvc_unit) = unit_table.get(id) {
  54. if let Specific::Service(srvc) = &srvc_unit.specific {
  55. let mut_state = &mut *srvc.state.write().unwrap();
  56. if let Some(socket) = &mut_state.srvc.notifications {
  57. let old_flags =
  58. nix::fcntl::fcntl(*fd, nix::fcntl::FcntlArg::F_GETFL)
  59. .unwrap();
  60. let old_flags =
  61. nix::fcntl::OFlag::from_bits(old_flags).unwrap();
  62. let mut new_flags = old_flags.clone();
  63. new_flags.insert(nix::fcntl::OFlag::O_NONBLOCK);
  64. nix::fcntl::fcntl(
  65. *fd,
  66. nix::fcntl::FcntlArg::F_SETFL(new_flags),
  67. )
  68. .unwrap();
  69. let bytes = {
  70. match socket.recv(&mut buf[..]) {
  71. Ok(b) => b,
  72. Err(e) => match e.kind() {
  73. std::io::ErrorKind::WouldBlock => 0,
  74. _ => panic!("{}", e),
  75. },
  76. }
  77. };
  78. nix::fcntl::fcntl(
  79. *fd,
  80. nix::fcntl::FcntlArg::F_SETFL(old_flags),
  81. )
  82. .unwrap();
  83. let note_str =
  84. String::from_utf8(buf[..bytes].to_vec()).unwrap();
  85. mut_state.srvc.notifications_buffer.push_str(&note_str);
  86. crate::notification_handler::handle_notifications_from_buffer(
  87. &mut mut_state.srvc,
  88. &srvc_unit.id.name,
  89. );
  90. }
  91. }
  92. }
  93. }
  94. }
  95. }
  96. Err(e) => {
  97. warn!("Error while selecting: {}", e);
  98. }
  99. }
  100. }
  101. }
  102. pub fn handle_all_std_out(run_info: ArcMutRuntimeInfo) {
  103. let eventfd = { run_info.read().unwrap().stdout_eventfd };
  104. loop {
  105. // need to collect all again. There might be a newly started service
  106. let fd_to_srvc_id = collect_from_srvc(run_info.clone(), |map, srvc, id| {
  107. if let Some(StdIo::Piped(r, _w)) = &srvc.stdout {
  108. map.insert(*r, id);
  109. }
  110. });
  111. let mut fdset = nix::sys::select::FdSet::new();
  112. for fd in fd_to_srvc_id.keys() {
  113. fdset.insert(*fd);
  114. }
  115. fdset.insert(eventfd.read_end());
  116. let result = nix::sys::select::select(None, Some(&mut fdset), None, None, None);
  117. let run_info_locked = run_info.read().unwrap();
  118. let unit_table = &run_info_locked.unit_table;
  119. match result {
  120. Ok(_) => {
  121. if fdset.contains(eventfd.read_end()) {
  122. trace!("Interrupted stdout select because the eventfd fired");
  123. reset_event_fd(eventfd);
  124. trace!("Reset eventfd value");
  125. }
  126. let mut buf = [0u8; 512];
  127. for (fd, id) in &fd_to_srvc_id {
  128. if fdset.contains(*fd) {
  129. if let Some(srvc_unit) = unit_table.get(id) {
  130. let name = srvc_unit.id.name.clone();
  131. if let Specific::Service(srvc) = &srvc_unit.specific {
  132. let mut_state = &mut *srvc.state.write().unwrap();
  133. let status = srvc_unit.common.status.read().unwrap();
  134. let old_flags =
  135. nix::fcntl::fcntl(*fd, nix::fcntl::FcntlArg::F_GETFL).unwrap();
  136. let old_flags = nix::fcntl::OFlag::from_bits(old_flags).unwrap();
  137. let mut new_flags = old_flags.clone();
  138. new_flags.insert(nix::fcntl::OFlag::O_NONBLOCK);
  139. nix::fcntl::fcntl(*fd, nix::fcntl::FcntlArg::F_SETFL(new_flags))
  140. .unwrap();
  141. ////
  142. let bytes = match nix::unistd::read(*fd, &mut buf[..]) {
  143. Ok(b) => b,
  144. Err(nix::Error::Sys(nix::errno::EWOULDBLOCK)) => 0,
  145. Err(e) => panic!("{}", e),
  146. };
  147. ////
  148. nix::fcntl::fcntl(*fd, nix::fcntl::FcntlArg::F_SETFL(old_flags))
  149. .unwrap();
  150. mut_state.srvc.stdout_buffer.extend(&buf[..bytes]);
  151. mut_state.srvc.log_stdout_lines(&name, &status).unwrap();
  152. }
  153. }
  154. }
  155. }
  156. }
  157. Err(e) => {
  158. warn!("Error while selecting: {}", e);
  159. }
  160. }
  161. }
  162. }
  163. pub fn handle_all_std_err(run_info: ArcMutRuntimeInfo) {
  164. let eventfd = { run_info.read().unwrap().stderr_eventfd };
  165. loop {
  166. // need to collect all again. There might be a newly started service
  167. let fd_to_srvc_id = collect_from_srvc(run_info.clone(), |map, srvc, id| {
  168. if let Some(StdIo::Piped(r, _w)) = &srvc.stderr {
  169. map.insert(*r, id);
  170. }
  171. });
  172. let mut fdset = nix::sys::select::FdSet::new();
  173. for fd in fd_to_srvc_id.keys() {
  174. fdset.insert(*fd);
  175. }
  176. fdset.insert(eventfd.read_end());
  177. let result = nix::sys::select::select(None, Some(&mut fdset), None, None, None);
  178. let run_info_locked = run_info.read().unwrap();
  179. let unit_table = &run_info_locked.unit_table;
  180. match result {
  181. Ok(_) => {
  182. if fdset.contains(eventfd.read_end()) {
  183. trace!("Interrupted stderr select because the eventfd fired");
  184. reset_event_fd(eventfd);
  185. trace!("Reset eventfd value");
  186. }
  187. let mut buf = [0u8; 512];
  188. for (fd, id) in &fd_to_srvc_id {
  189. if fdset.contains(*fd) {
  190. if let Some(srvc_unit) = unit_table.get(id) {
  191. let name = srvc_unit.id.name.clone();
  192. if let Specific::Service(srvc) = &srvc_unit.specific {
  193. let mut_state = &mut *srvc.state.write().unwrap();
  194. let status = srvc_unit.common.status.read().unwrap();
  195. let old_flags =
  196. nix::fcntl::fcntl(*fd, nix::fcntl::FcntlArg::F_GETFL).unwrap();
  197. let old_flags = nix::fcntl::OFlag::from_bits(old_flags).unwrap();
  198. let mut new_flags = old_flags.clone();
  199. new_flags.insert(nix::fcntl::OFlag::O_NONBLOCK);
  200. nix::fcntl::fcntl(*fd, nix::fcntl::FcntlArg::F_SETFL(new_flags))
  201. .unwrap();
  202. ////
  203. let bytes = match nix::unistd::read(*fd, &mut buf[..]) {
  204. Ok(b) => b,
  205. Err(nix::Error::Sys(nix::errno::EWOULDBLOCK)) => 0,
  206. Err(e) => panic!("{}", e),
  207. };
  208. ////
  209. nix::fcntl::fcntl(*fd, nix::fcntl::FcntlArg::F_SETFL(old_flags))
  210. .unwrap();
  211. mut_state.srvc.stderr_buffer.extend(&buf[..bytes]);
  212. mut_state.srvc.log_stderr_lines(&name, &status).unwrap();
  213. }
  214. }
  215. }
  216. }
  217. }
  218. Err(e) => {
  219. warn!("Error while selecting: {}", e);
  220. }
  221. }
  222. }
  223. }
  224. pub fn handle_notification_message(msg: &str, srvc: &mut Service, name: &str) {
  225. let split: Vec<_> = msg.split('=').collect();
  226. match split[0] {
  227. "STATUS" => {
  228. srvc.status_msgs.push(split[1].to_owned());
  229. trace!(
  230. "New status message pushed from service {}: {}",
  231. name,
  232. srvc.status_msgs.last().unwrap()
  233. );
  234. }
  235. "READY" => {
  236. srvc.signaled_ready = true;
  237. }
  238. _ => {
  239. warn!("Unknown notification name{}", split[0]);
  240. }
  241. }
  242. }
  243. pub fn handle_notifications_from_buffer(srvc: &mut Service, name: &str) {
  244. while srvc.notifications_buffer.contains('\n') {
  245. let (line, rest) = srvc
  246. .notifications_buffer
  247. .split_at(srvc.notifications_buffer.find('\n').unwrap());
  248. let line = line.to_owned();
  249. srvc.notifications_buffer = rest[1..].to_owned();
  250. handle_notification_message(&line, srvc, name);
  251. }
  252. }