diff --git a/src/agent/rustjail/src/cgroups/fs/mod.rs b/src/agent/rustjail/src/cgroups/fs/mod.rs index 7f41cb4dd..04aa57537 100644 --- a/src/agent/rustjail/src/cgroups/fs/mod.rs +++ b/src/agent/rustjail/src/cgroups/fs/mod.rs @@ -349,14 +349,34 @@ fn set_memory_resources(cg: &cgroups::Cgroup, memory: &LinuxMemory, update: bool mem_controller.set_kmem_limit(-1)?; } - set_resource!(mem_controller, set_limit, memory, limit); - set_resource!(mem_controller, set_soft_limit, memory, reservation); - set_resource!(mem_controller, set_kmem_limit, memory, kernel); - set_resource!(mem_controller, set_tcp_limit, memory, kernel_tcp); + // If the memory update is set to -1 we should also + // set swap to -1, it means unlimited memory. + let mut swap = memory.swap.unwrap_or(0); + if memory.limit == Some(-1) { + swap = -1; + } - if let Some(swap) = memory.swap { - // set memory swap - let swap = if cg.v2() { + if memory.limit.is_some() && swap != 0 { + let memstat = get_memory_stats(cg) + .into_option() + .ok_or_else(|| anyhow!("failed to get the cgroup memory stats"))?; + let memusage = memstat.get_usage(); + + // When update memory limit, the kernel would check the current memory limit + // set against the new swap setting, if the current memory limit is large than + // the new swap, then set limit first, otherwise the kernel would complain and + // refused to set; on the other hand, if the current memory limit is smaller than + // the new swap, then we should set the swap first and then set the memor limit. + if swap == -1 || memusage.get_limit() < swap as u64 { + mem_controller.set_memswap_limit(swap)?; + set_resource!(mem_controller, set_limit, memory, limit); + } else { + set_resource!(mem_controller, set_limit, memory, limit); + mem_controller.set_memswap_limit(swap)?; + } + } else { + set_resource!(mem_controller, set_limit, memory, limit); + swap = if cg.v2() { convert_memory_swap_to_v2_value(swap, memory.limit.unwrap_or(0))? } else { swap @@ -366,6 +386,10 @@ fn set_memory_resources(cg: &cgroups::Cgroup, memory: &LinuxMemory, update: bool } } + set_resource!(mem_controller, set_soft_limit, memory, reservation); + set_resource!(mem_controller, set_kmem_limit, memory, kernel); + set_resource!(mem_controller, set_tcp_limit, memory, kernel_tcp); + if let Some(swappiness) = memory.swappiness { if (0..=100).contains(&swappiness) { mem_controller.set_swappiness(swappiness as u64)?; diff --git a/src/agent/src/main.rs b/src/agent/src/main.rs index 595951bc5..d7d2aaf19 100644 --- a/src/agent/src/main.rs +++ b/src/agent/src/main.rs @@ -248,6 +248,7 @@ fn main() -> std::result::Result<(), Box> { } if args.len() == 2 && args[1] == "init" { + reset_sigpipe(); rustjail::container::init_child(); exit(0); } @@ -358,5 +359,16 @@ fn sethostname(hostname: &OsStr) -> Result<()> { } } +// The Rust standard library had suppressed the default SIGPIPE behavior, +// see https://github.com/rust-lang/rust/pull/13158. +// Since the parent's signal handler would be inherited by it's child process, +// thus we should re-enable the standard SIGPIPE behavior as a workaround to +// fix the issue of https://github.com/kata-containers/kata-containers/issues/1887. +fn reset_sigpipe() { + unsafe { + libc::signal(libc::SIGPIPE, libc::SIG_DFL); + } +} + use crate::config::AgentConfig; use std::os::unix::io::{FromRawFd, RawFd}; diff --git a/src/runtime/virtcontainers/virtiofsd.go b/src/runtime/virtcontainers/virtiofsd.go index 9b4bc27aa..be2c0e069 100644 --- a/src/runtime/virtcontainers/virtiofsd.go +++ b/src/runtime/virtcontainers/virtiofsd.go @@ -75,6 +75,8 @@ func (v *virtiofsd) getSocketFD() (*os.File, error) { if err != nil { return nil, err } + + // no longer needed since fd is a dup defer listener.Close() listener.SetUnlinkOnClose(false) @@ -98,6 +100,7 @@ func (v *virtiofsd) Start(ctx context.Context) (int, error) { if err != nil { return 0, err } + defer socketFD.Close() cmd.ExtraFiles = append(cmd.ExtraFiles, socketFD) @@ -128,7 +131,7 @@ func (v *virtiofsd) Start(ctx context.Context) (int, error) { v.wait = waitVirtiofsReady } - return pid, socketFD.Close() + return cmd.Process.Pid, nil } func (v *virtiofsd) Stop(ctx context.Context) error {