From 01e45800dc674a7b3e1e9e6629898ce150443721 Mon Sep 17 00:00:00 2001 From: Liu Jiang Date: Sun, 12 Dec 2021 11:29:01 +0800 Subject: [PATCH] shim: release fd when error happens in RemotePublisher::connect() A RawFd won't be automatically released when going out of scope, so we need to close the just created RawFd when error happens in RemotePublisher::connect(). Signed-off-by: Liu Jiang --- crates/shim/src/publisher.rs | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/crates/shim/src/publisher.rs b/crates/shim/src/publisher.rs index 51e66ea..2ba8001 100644 --- a/crates/shim/src/publisher.rs +++ b/crates/shim/src/publisher.rs @@ -16,7 +16,6 @@ //! Implements a client to publish events from the shim back to containerd. -use std::os::unix::io::RawFd; use std::time::{SystemTime, UNIX_EPOCH}; use containerd_shim_client as client; @@ -38,18 +37,22 @@ pub struct RemotePublisher { impl RemotePublisher { /// Connect to containerd's TTRPC endpoint. + /// /// containerd uses `/run/containerd/containerd.sock.ttrpc` by default pub fn new(address: impl AsRef) -> Result { - let fd = Self::connect(address)?; - let client = Client::new(fd); + let client = Self::connect(address)?; Ok(RemotePublisher { client: EventsClient::new(client), }) } - fn connect(address: impl AsRef) -> Result { + fn connect(address: impl AsRef) -> Result { use nix::sys::socket::*; + use nix::unistd::close; + + let unix_addr = UnixAddr::new(address.as_ref())?; + let sock_addr = SockAddr::Unix(unix_addr); // SOCK_CLOEXEC flag is Linux specific #[cfg(target_os = "linux")] @@ -65,18 +68,23 @@ impl RemotePublisher { #[cfg(not(target_os = "linux"))] { use nix::fcntl::{fcntl, FcntlArg, FdFlag}; - fcntl(fd, FcntlArg::F_SETFD(FdFlag::FD_CLOEXEC))?; + fcntl(fd, FcntlArg::F_SETFD(FdFlag::FD_CLOEXEC)).map_err(|e| { + let _ = close(fd); + e + })?; } - let unix_addr = UnixAddr::new(address.as_ref())?; - let sock_addr = SockAddr::Unix(unix_addr); + connect(fd, &sock_addr).map_err(|e| { + let _ = close(fd); + e + })?; - connect(fd, &sock_addr)?; - - Ok(fd) + // Client::new() takes ownership of the RawFd. + Ok(Client::new(fd)) } - /// Publish new event. + /// Publish a new event. + /// /// Event object can be anything that Protobuf able serialize (e.g. implement `Message` trait). pub fn publish( &self,