From 1ce3fc5e30a39cf5c0216cc5baa79eceedcc1173 Mon Sep 17 00:00:00 2001 From: overweight Date: Wed, 29 Dec 2021 10:14:38 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=E6=B7=BB=E5=8A=A0=E9=83=A8=E5=88=86?= =?UTF-8?q?=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- run_with_sd/patches/0004-add-signal.patch | 144 ++++++++++--------- run_with_sd/patches/README.md | 5 + run_with_sd/systemd-dockerimg/build.sh | 7 +- run_with_sd/systemd-dockerimg/rpms/README.md | 1 + 4 files changed, 83 insertions(+), 74 deletions(-) create mode 100644 run_with_sd/patches/README.md create mode 100644 run_with_sd/systemd-dockerimg/rpms/README.md diff --git a/run_with_sd/patches/0004-add-signal.patch b/run_with_sd/patches/0004-add-signal.patch index 988c32a8..a1f9f921 100644 --- a/run_with_sd/patches/0004-add-signal.patch +++ b/run_with_sd/patches/0004-add-signal.patch @@ -1,14 +1,14 @@ -From 81e1652c378be010b64b6e49b22ccaaebd709ecc Mon Sep 17 00:00:00 2001 +From 12c8379d3b81bf0a63a50dfd1ea243dcb102242e Mon Sep 17 00:00:00 2001 From: rpm-build -Date: Tue, 21 Dec 2021 15:09:31 +0800 +Date: Wed, 29 Dec 2021 09:25:37 +0800 Subject: [PATCH] add signal --- - src/core/manager.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 67 insertions(+) + src/core/manager.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 69 insertions(+) diff --git a/src/core/manager.c b/src/core/manager.c -index 58345e1..e509e8d 100644 +index 58345e1..d75cbd4 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -524,6 +524,7 @@ static int manager_setup_signals(Manager *m) { @@ -19,75 +19,77 @@ index 58345e1..e509e8d 100644 /* ... space for more special targets ... */ -@@ -2778,6 +2779,72 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t +@@ -2778,6 +2779,74 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t switch (sfsi.ssi_signo - SIGRTMIN) { -+ case 7: -+ siginfo_t si = { -+ .si_signo = sfsi.ssi_signo, -+ .si_code = sfsi.ssi_code, -+ .si_pid = sfsi.ssi_pid, -+ .si_status = sfsi.ssi_status -+ }; -+ if (IN_SET(si.si_code, CLD_EXITED, CLD_KILLED, CLD_DUMPED)) { -+ _cleanup_free_ Unit **array_copy = NULL; -+ _cleanup_free_ char *name = NULL; -+ Unit *u1, *u2, **array; -+ -+ (void) get_process_comm(si.si_pid, &name); -+ -+ log_debug("Child "PID_FMT" (%s) died (code=%s, status=%i/%s)", -+ si.si_pid, strna(name), -+ sigchld_code_to_string(si.si_code), -+ si.si_status, -+ strna(si.si_code == CLD_EXITED -+ ? exit_status_to_string(si.si_status, EXIT_STATUS_FULL) -+ : signal_to_string(si.si_status))); -+ -+ /* Increase the generation counter used for filtering out duplicate unit invocations */ -+ m->sigchldgen++; -+ -+ /* And now figure out the unit this belongs to, it might be multiple... */ -+ u1 = manager_get_unit_by_pid_cgroup(m, si.si_pid); -+ u2 = hashmap_get(m->watch_pids, PID_TO_PTR(si.si_pid)); -+ array = hashmap_get(m->watch_pids, PID_TO_PTR(-si.si_pid)); -+ if (array) { -+ size_t cnt = 0; -+ -+ /* Count how many entries the array has */ -+ while (array[cnt]) -+ cnt++; -+ -+ /* Make a copy of the array so that we don't trip up on the array changing beneath us */ -+ array_copy = newdup(Unit*, array, cnt+1); -+ if (!array_copy) -+ log_oom(); -+ } -+ -+ /* Finally, execute them all. Note that u1, u2 and the array might contain duplicates, but -+ * that's fine, manager_invoke_sigchld_event() will ensure we only invoke the handlers once for -+ * each iteration. */ -+ if (u1) { -+ /* We check for oom condition, in case we got SIGCHLD before the oom notification. -+ * We only do this for the cgroup the PID belonged to. */ -+ (void) unit_check_oom(u1); -+ -+ /* This only logs for now. In the future when the interface for kills/notifications -+ * is more stable we can extend service results table similar to how kernel oom kills -+ * are managed. */ -+ (void) unit_check_oomd_kill(u1); -+ -+ manager_invoke_sigchld_event(m, u1, &si); -+ } -+ if (u2) -+ manager_invoke_sigchld_event(m, u2, &si); -+ if (array_copy) -+ for (size_t i = 0; array_copy[i]; i++) - manager_invoke_sigchld_event(m, array_copy[i], &si); -+ syscall(__NR_rt_sigqueueinfo, 1, sfsi.ssi_signo, &si); -+ } -+ break; ++ case 7: ++ { ++ siginfo_t si = { ++ .si_signo = sfsi.ssi_signo, ++ .si_code = sfsi.ssi_code, ++ .si_pid = sfsi.ssi_pid, ++ .si_status = sfsi.ssi_status ++ }; ++ if (IN_SET(si.si_code, CLD_EXITED, CLD_KILLED, CLD_DUMPED)) { ++ _cleanup_free_ Unit **array_copy = NULL; ++ _cleanup_free_ char *name = NULL; ++ Unit *u1, *u2, **array; ++ ++ (void) get_process_comm(si.si_pid, &name); ++ ++ log_debug("Child "PID_FMT" (%s) died (code=%s, status=%i/%s)", ++ si.si_pid, strna(name), ++ sigchld_code_to_string(si.si_code), ++ si.si_status, ++ strna(si.si_code == CLD_EXITED ++ ? exit_status_to_string(si.si_status, EXIT_STATUS_FULL) ++ : signal_to_string(si.si_status))); ++ ++ /* Increase the generation counter used for filtering out duplicate unit invocations */ ++ m->sigchldgen++; ++ ++ /* And now figure out the unit this belongs to, it might be multiple... */ ++ u1 = manager_get_unit_by_pid_cgroup(m, si.si_pid); ++ u2 = hashmap_get(m->watch_pids, PID_TO_PTR(si.si_pid)); ++ array = hashmap_get(m->watch_pids, PID_TO_PTR(-si.si_pid)); ++ if (array) { ++ size_t cnt = 0; ++ ++ /* Count how many entries the array has */ ++ while (array[cnt]) ++ cnt++; ++ ++ /* Make a copy of the array so that we don't trip up on the array changing beneath us */ ++ array_copy = newdup(Unit*, array, cnt+1); ++ if (!array_copy) ++ log_oom(); ++ } ++ ++ /* Finally, execute them all. Note that u1, u2 and the array might contain duplicates, but ++ * that's fine, manager_invoke_sigchld_event() will ensure we only invoke the handlers once for ++ * each iteration. */ ++ if (u1) { ++ /* We check for oom condition, in case we got SIGCHLD before the oom notification. ++ * We only do this for the cgroup the PID belonged to. */ ++ (void) unit_check_oom(u1); ++ ++ /* This only logs for now. In the future when the interface for kills/notifications ++ * is more stable we can extend service results table similar to how kernel oom kills ++ * are managed. */ ++ (void) unit_check_oomd_kill(u1); ++ ++ manager_invoke_sigchld_event(m, u1, &si); ++ } ++ if (u2) ++ manager_invoke_sigchld_event(m, u2, &si); ++ if (array_copy) ++ for (size_t i = 0; array_copy[i]; i++) ++ manager_invoke_sigchld_event(m, array_copy[i], &si); ++ syscall(__NR_rt_sigqueueinfo, 1, sfsi.ssi_signo, &si); ++ } ++ break; ++ } + case 20: manager_override_show_status(m, SHOW_STATUS_YES, "signal"); diff --git a/run_with_sd/patches/README.md b/run_with_sd/patches/README.md new file mode 100644 index 00000000..aa3aba72 --- /dev/null +++ b/run_with_sd/patches/README.md @@ -0,0 +1,5 @@ +1. 下载[systemd-248-13.oe1.src.rpm](https://repo.openeuler.org/openEuler-21.09/source/Packages/systemd-248-13.oe1.src.rpm) +2. 执行`rpm -ivh systemd-248-13.oe1.src.rpm`, 源码安装到`~/rpmbuild` +3. 将patches目录下的内容拷贝覆盖到`~/rpmbuild/SOURCES` +4. 执行`rpmbuild -ba ~/rpmbuild/SOURCES/systemd.spec --nocheck` +5. 生成的rpm在`~/rpmbuild/RPMS/x86_64/`下 \ No newline at end of file diff --git a/run_with_sd/systemd-dockerimg/build.sh b/run_with_sd/systemd-dockerimg/build.sh index 8b623f05..769a4f50 100755 --- a/run_with_sd/systemd-dockerimg/build.sh +++ b/run_with_sd/systemd-dockerimg/build.sh @@ -1,10 +1,11 @@ #!/bin/bash yum -c openEuler.repo --installroot=$PWD/rootfs install systemd -y -cp -a rpms/systemd*.rpm rootfs/ +mkdir -p rootfs/rpms +cp -a rpms/systemd*.rpm rootfs/rpms if [ $? -ne 0 ]; then echo "put your rpms into dir rpms" exit 1 fi -chroot rootfs /bin/bash -c "rpm -Fvh *" -rm -rf rootfs/systemd*.rpm +chroot rootfs /bin/bash -c "rpm -Fvh /rpms/*" +rm -rf rootfs/rpms/systemd*.rpm docker build --no-cache --tag systemd . diff --git a/run_with_sd/systemd-dockerimg/rpms/README.md b/run_with_sd/systemd-dockerimg/rpms/README.md new file mode 100644 index 00000000..f6f124a8 --- /dev/null +++ b/run_with_sd/systemd-dockerimg/rpms/README.md @@ -0,0 +1 @@ +生成在`~/rpmbuild/RPMS/x86_64/`下rpms, 拷贝到此目录 \ No newline at end of file -- Gitee From f17176ac9a8df97b01228b3a117081ebd91bf4a4 Mon Sep 17 00:00:00 2001 From: overweight Date: Thu, 9 Dec 2021 20:32:03 +0800 Subject: [PATCH 2/4] add rust api guidelines --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dbebf4e6..7404a9ee 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,12 +2,12 @@ ***感谢你对本项目的关注, 同时欢迎为本项目建言献策,提交代码,维护支持!*** - - -关于如何贡献本项目, 参考: +关于**如何贡献**及**编程约定**,请参考: - [openEuler贡献攻略](https://www.openeuler.org/zh/community/contribution/)。 - [行为准则](https://www.openeuler.org/zh/community/conduct/) +- [rust API指南](https://zjp-cn.github.io/api-guidelines/) +- [rust 设计模式](http://chuxiuhong.com/chuxiuhong-rust-patterns-zh/) 我们强烈推荐, -- Gitee From b7912b90468fa1ec32602c4c9c574891cd351b55 Mon Sep 17 00:00:00 2001 From: overweight Date: Thu, 9 Dec 2021 20:52:32 +0800 Subject: [PATCH 3/4] rework event poll --- src/event/src/lib.rs | 24 ++++++++- src/event/src/{sys => poll}/epoll.rs | 75 +++++++++++++++++----------- src/event/src/poll/mod.rs | 47 +++++++++++++++++ src/event/src/sys/mod.rs | 43 ---------------- 4 files changed, 115 insertions(+), 74 deletions(-) rename src/event/src/{sys => poll}/epoll.rs (44%) create mode 100644 src/event/src/poll/mod.rs delete mode 100644 src/event/src/sys/mod.rs diff --git a/src/event/src/lib.rs b/src/event/src/lib.rs index e79c79d9..0c047083 100644 --- a/src/event/src/lib.rs +++ b/src/event/src/lib.rs @@ -1 +1,23 @@ -mod sys; +//pub mod events; +pub mod poll; +//pub mod sources; + +#[allow(unused_macros)] +#[macro_export] +macro_rules! syscall { + ($fn: ident ( $($arg: expr),* $(,)* ) ) => {{ + let res = unsafe { libc::$fn($($arg, )*) }; + if res == -1 { + Err(std::io::Error::last_os_error()) + } else { + Ok(res) + } + }}; +} + +#[cfg(test)] +mod test { + #[cfg(unix)] + #[test] + fn build() {} +} diff --git a/src/event/src/sys/epoll.rs b/src/event/src/poll/epoll.rs similarity index 44% rename from src/event/src/sys/epoll.rs rename to src/event/src/poll/epoll.rs index ef6caaf1..8811efe9 100644 --- a/src/event/src/sys/epoll.rs +++ b/src/event/src/poll/epoll.rs @@ -1,53 +1,59 @@ -use std::{io, os::unix::io::RawFd, ptr, sync::atomic::{AtomicUsize, Ordering::Relaxed}}; use libc::{epoll_event, EPOLL_CLOEXEC, EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD}; +use std::os::unix::io::{AsRawFd, RawFd}; +use std::sync::atomic::{AtomicUsize, Ordering::Relaxed}; +use std::{io, ptr}; -#[allow(unused_macros)] -macro_rules! syscall { - ($fn: ident ( $($arg: expr),* $(,)* ) ) => {{ - let res = unsafe { libc::$fn($($arg, )*) }; - if res == -1 { - Err(std::io::Error::last_os_error()) - } else { - Ok(res) - } - }}; -} +use crate::syscall; + +const LOWEST_FD: libc::c_int = 3; -#[derive(Debug)] -pub struct Epoll { +#[derive(Debug, Default)] +pub(crate) struct Epoll { epoll_fd: RawFd, n_sources: AtomicUsize, } impl Epoll { - pub fn new() -> io::Result { - syscall!(epoll_create1(EPOLL_CLOEXEC)).map( | ep | - Epoll { epoll_fd: ep, - n_sources: AtomicUsize::new(0), + pub(crate) fn new() -> io::Result { + syscall!(epoll_create1(EPOLL_CLOEXEC)).map(|ep| Epoll { + epoll_fd: ep, + n_sources: AtomicUsize::new(0), }) } - pub fn poll(&mut self, timeout: Option) -> io::Result> { + pub(crate) fn try_clone(&self) -> io::Result { + syscall!(fcntl(self.epoll_fd, libc::F_DUPFD_CLOEXEC, LOWEST_FD)).map(|ep| Epoll { + epoll_fd: ep, + n_sources: AtomicUsize::new(0), + }) + } + + pub(crate) fn poll( + &mut self, + timeout: Option, + ) -> io::Result> { let mut events = Vec::::with_capacity(self.n_sources.load(Relaxed)); let _n_ready = syscall!(epoll_wait( self.epoll_fd, events.as_mut_ptr(), events.capacity() as i32, - timeout.map(|to| to.as_millis() as libc::c_int).unwrap_or(-1), + timeout + .map(|to| to.as_millis() as libc::c_int) + .unwrap_or(-1), )); Ok(events) } - - pub fn register(&mut self, fd: RawFd, event: &mut epoll_event) -> io::Result<()> { + + pub(crate) fn register(&mut self, fd: RawFd, event: &mut epoll_event) -> io::Result<()> { self.n_sources.fetch_add(1, Relaxed); syscall!(epoll_ctl(self.epoll_fd, EPOLL_CTL_ADD, fd, event)).map(|_| ()) } - pub fn reregister(&mut self, fd: RawFd, event: &mut epoll_event) -> io::Result<()> { + pub(crate) fn reregister(&mut self, fd: RawFd, event: &mut epoll_event) -> io::Result<()> { syscall!(epoll_ctl(self.epoll_fd, EPOLL_CTL_MOD, fd, event)).map(|_| ()) } - - pub fn unregister(&mut self, fd: RawFd) -> io::Result<()> { + + pub(crate) fn unregister(&mut self, fd: RawFd) -> io::Result<()> { self.n_sources.fetch_sub(1, Relaxed); syscall!(epoll_ctl(self.epoll_fd, EPOLL_CTL_DEL, fd, ptr::null_mut())).map(|_| ()) } @@ -59,10 +65,16 @@ impl Drop for Epoll { } } +impl AsRawFd for Epoll { + fn as_raw_fd(&self) -> RawFd { + self.epoll_fd + } +} + #[cfg(test)] mod test { - use libc::EPOLLIN; use super::Epoll; + use libc::EPOLLIN; #[cfg(unix)] #[test] @@ -74,8 +86,11 @@ mod test { #[test] fn epoll_add() { let mut poll = Epoll::new().unwrap(); - let mut events = libc::epoll_event {events: EPOLLIN as u32, u64: 0,}; - poll.register(poll.epoll_fd, &mut events); - poll.unregister(poll.epoll_fd); + let mut events = libc::epoll_event { + events: EPOLLIN as u32, + u64: 0, + }; + let _ = poll.register(poll.epoll_fd, &mut events); + let _ = poll.unregister(poll.epoll_fd); } -} \ No newline at end of file +} diff --git a/src/event/src/poll/mod.rs b/src/event/src/poll/mod.rs new file mode 100644 index 00000000..00125ca3 --- /dev/null +++ b/src/event/src/poll/mod.rs @@ -0,0 +1,47 @@ +mod epoll; + +use epoll::Epoll; +use libc::epoll_event; +use std::os::unix::{io::AsRawFd, io::RawFd}; +use std::{io, time}; + +#[derive(Debug, Default)] +pub struct Poll { + poller: Epoll, +} + +impl Poll { + pub fn new() -> io::Result { + Ok(Poll { + poller: Epoll::new()?, + }) + } + + pub fn try_clone(&self) -> io::Result { + Ok(Poll { + poller: self.poller.try_clone().unwrap(), + }) + } + + pub fn poll(&mut self, timeout: Option) -> io::Result> { + self.poller.poll(timeout) + } + + pub fn register(&mut self, fd: RawFd, event: &mut epoll_event) -> io::Result<()> { + self.poller.register(fd, event) + } + + pub fn reregister(&mut self, fd: RawFd, event: &mut epoll_event) -> io::Result<()> { + self.poller.reregister(fd, event) + } + + pub fn unregister(&mut self, fd: RawFd) -> io::Result<()> { + self.poller.unregister(fd) + } +} + +impl AsRawFd for Poll { + fn as_raw_fd(&self) -> RawFd { + self.poller.as_raw_fd() + } +} diff --git a/src/event/src/sys/mod.rs b/src/event/src/sys/mod.rs deleted file mode 100644 index 393d11a9..00000000 --- a/src/event/src/sys/mod.rs +++ /dev/null @@ -1,43 +0,0 @@ -mod epoll; - -use std::{io, os::unix::io::RawFd, time}; -use epoll::Epoll as Epoll; -use libc::epoll_event; - -#[derive(Debug)] -pub struct Poll { - poller: Epoll, -} - -impl Poll { - pub(crate) fn new() -> io::Result { - Ok( Poll { poller: Epoll::new()?, }) - } - - pub(crate) fn poll( - &mut self, - timeout: Option, - ) -> io::Result> { - self.poller.poll(timeout) - } - - pub(crate) unsafe fn register( - &mut self, - fd: RawFd, - event: &mut epoll_event, - ) -> io::Result<()> { - self.poller.register(fd, event) - } - - pub(crate) unsafe fn reregister( - &mut self, - fd: RawFd, - event: &mut epoll_event, - ) -> io::Result<()> { - self.poller.reregister(fd, event) - } - - pub(crate) fn unregister(&mut self, fd: RawFd) -> io::Result<()> { - self.poller.unregister(fd) - } -} -- Gitee From c175631105760d45d53fb1bdbd1d8c13f6c945ca Mon Sep 17 00:00:00 2001 From: Hexiaowen Date: Tue, 28 Dec 2021 07:41:36 +0000 Subject: [PATCH 4/4] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=93=BE=E6=8E=A5?= =?UTF-8?q?=E6=8C=87=E5=90=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- run_with_sd/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run_with_sd/README.md b/run_with_sd/README.md index 0ab5f7cc..b047cce2 100644 --- a/run_with_sd/README.md +++ b/run_with_sd/README.md @@ -19,7 +19,7 @@ ## 验证 至少有两种方式验证。 ### 容器方式(在容器中非1号进程运行systemd) -1. 使用[patches](patches/)目录下的适配代码编译systemd,并将输出的rpms,放在![systemd-dockerimg/rpms](systemd-dockerimg/rpms/)目录下。 +1. 使用[patches](patches/)目录下的适配代码编译systemd,并将输出的rpms,放在[systemd-dockerimg/rpms](systemd-dockerimg/rpms/)目录下。 2. 使用[build.sh](systemd-dockerimg/build.sh)构建systemd的容器image。可以`chroot rootfs /bin/bash`,通过`password`命令修改登录密码,然后执行`build.sh`更新镜像。 3. 修改仓库根目录下的Dockerfile,修改`FROM scratch`为`FROM systemd`, 去除`#RUN rm -f /sbin/init`注释 并在根目录下执行`./docker-run.sh /usr/lib/systemd/systemd` 4. 可另起窗口,执行`docker exec -it prun bash`进入容器。 -- Gitee