[{"id":21419,"web_url":"https://patchwork.libcamera.org/comment/21419/","msgid":"<20211130075426.xoyzmatab44hq3kz@uno.localdomain>","date":"2021-11-30T07:54:26","subject":"Re: [libcamera-devel] [PATCH v4 10/22] libcamera: ipc_unixsocket:\n\tUse UniqueFD for a file descriptor","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Laurent,\n\nOn Tue, Nov 30, 2021 at 05:38:08AM +0200, Laurent Pinchart wrote:\n> From: Hirokazu Honda <hiroh@chromium.org>\n>\n> IPCUnixSocket::create() creates two file descriptors. One of\n> them is stored in IPCUnixSocket and the other is returned to a\n> caller. This clarifies the ownership using UniqueFD.\n>\n> Signed-off-by: Hirokazu Honda <hiroh@chromium.org>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> Reviewed-by: Hirokazu Honda <hiroh@chromium.org>\n\nReviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n\nThanks\n  j\n\n> ---\n> Changes since v2:\n>\n> - Pass UniqueFD to IPCUnixSocket::bind()\n> - Return {}\n> ---\n>  include/libcamera/internal/ipc_unixsocket.h   |  7 +--\n>  src/libcamera/ipc_pipe_unixsocket.cpp         |  8 ++--\n>  src/libcamera/ipc_unixsocket.cpp              | 43 ++++++++++---------\n>  test/ipc/unixsocket.cpp                       | 14 +++---\n>  test/ipc/unixsocket_ipc.cpp                   |  8 ++--\n>  .../module_ipa_proxy_worker.cpp.tmpl          | 13 +++---\n>  6 files changed, 49 insertions(+), 44 deletions(-)\n>\n> diff --git a/include/libcamera/internal/ipc_unixsocket.h b/include/libcamera/internal/ipc_unixsocket.h\n> index 5010b66a2bda..3963d182ffa6 100644\n> --- a/include/libcamera/internal/ipc_unixsocket.h\n> +++ b/include/libcamera/internal/ipc_unixsocket.h\n> @@ -12,6 +12,7 @@\n>  #include <vector>\n>\n>  #include <libcamera/base/signal.h>\n> +#include <libcamera/base/unique_fd.h>\n>\n>  namespace libcamera {\n>\n> @@ -28,8 +29,8 @@ public:\n>  \tIPCUnixSocket();\n>  \t~IPCUnixSocket();\n>\n> -\tint create();\n> -\tint bind(int fd);\n> +\tUniqueFD create();\n> +\tint bind(UniqueFD fd);\n>  \tvoid close();\n>  \tbool isBound() const;\n>\n> @@ -49,7 +50,7 @@ private:\n>\n>  \tvoid dataNotifier();\n>\n> -\tint fd_;\n> +\tUniqueFD fd_;\n>  \tbool headerReceived_;\n>  \tstruct Header header_;\n>  \tEventNotifier *notifier_;\n> diff --git a/src/libcamera/ipc_pipe_unixsocket.cpp b/src/libcamera/ipc_pipe_unixsocket.cpp\n> index 533560cf95d3..65277500ff42 100644\n> --- a/src/libcamera/ipc_pipe_unixsocket.cpp\n> +++ b/src/libcamera/ipc_pipe_unixsocket.cpp\n> @@ -31,14 +31,14 @@ IPCPipeUnixSocket::IPCPipeUnixSocket(const char *ipaModulePath,\n>  \targs.push_back(ipaModulePath);\n>\n>  \tsocket_ = std::make_unique<IPCUnixSocket>();\n> -\tint fd = socket_->create();\n> -\tif (fd < 0) {\n> +\tUniqueFD fd = socket_->create();\n> +\tif (!fd.isValid()) {\n>  \t\tLOG(IPCPipe, Error) << \"Failed to create socket\";\n>  \t\treturn;\n>  \t}\n>  \tsocket_->readyRead.connect(this, &IPCPipeUnixSocket::readyRead);\n> -\targs.push_back(std::to_string(fd));\n> -\tfds.push_back(fd);\n> +\targs.push_back(std::to_string(fd.get()));\n> +\tfds.push_back(fd.release());\n>\n>  \tproc_ = std::make_unique<Process>();\n>  \tint ret = proc_->start(ipaProxyWorkerPath, args, fds);\n> diff --git a/src/libcamera/ipc_unixsocket.cpp b/src/libcamera/ipc_unixsocket.cpp\n> index bd32fca3a678..1980d374cea8 100644\n> --- a/src/libcamera/ipc_unixsocket.cpp\n> +++ b/src/libcamera/ipc_unixsocket.cpp\n> @@ -7,6 +7,7 @@\n>\n>  #include \"libcamera/internal/ipc_unixsocket.h\"\n>\n> +#include <array>\n>  #include <poll.h>\n>  #include <string.h>\n>  #include <sys/socket.h>\n> @@ -68,7 +69,7 @@ LOG_DEFINE_CATEGORY(IPCUnixSocket)\n>   */\n>\n>  IPCUnixSocket::IPCUnixSocket()\n> -\t: fd_(-1), headerReceived_(false), notifier_(nullptr)\n> +\t: headerReceived_(false), notifier_(nullptr)\n>  {\n>  }\n>\n> @@ -86,9 +87,9 @@ IPCUnixSocket::~IPCUnixSocket()\n>   * to the remote process, where it can be used with IPCUnixSocket::bind() to\n>   * bind the remote side socket.\n>   *\n> - * \\return A file descriptor on success, negative error code on failure\n> + * \\return A file descriptor. It is valid on success or invalid otherwise.\n>   */\n> -int IPCUnixSocket::create()\n> +UniqueFD IPCUnixSocket::create()\n>  {\n>  \tint sockets[2];\n>  \tint ret;\n> @@ -98,14 +99,18 @@ int IPCUnixSocket::create()\n>  \t\tret = -errno;\n>  \t\tLOG(IPCUnixSocket, Error)\n>  \t\t\t<< \"Failed to create socket pair: \" << strerror(-ret);\n> -\t\treturn ret;\n> +\t\treturn {};\n>  \t}\n>\n> -\tret = bind(sockets[0]);\n> -\tif (ret)\n> -\t\treturn ret;\n> +\tstd::array<UniqueFD, 2> socketFds{\n> +\t\tUniqueFD(sockets[0]),\n> +\t\tUniqueFD(sockets[1]),\n> +\t};\n>\n> -\treturn sockets[1];\n> +\tif (bind(std::move(socketFds[0])) < 0)\n> +\t\treturn {};\n> +\n> +\treturn std::move(socketFds[1]);\n>  }\n>\n>  /**\n> @@ -118,13 +123,13 @@ int IPCUnixSocket::create()\n>   *\n>   * \\return 0 on success or a negative error code otherwise\n>   */\n> -int IPCUnixSocket::bind(int fd)\n> +int IPCUnixSocket::bind(UniqueFD fd)\n>  {\n>  \tif (isBound())\n>  \t\treturn -EINVAL;\n>\n> -\tfd_ = fd;\n> -\tnotifier_ = new EventNotifier(fd_, EventNotifier::Read);\n> +\tfd_ = std::move(fd);\n> +\tnotifier_ = new EventNotifier(fd_.get(), EventNotifier::Read);\n>  \tnotifier_->activated.connect(this, &IPCUnixSocket::dataNotifier);\n>\n>  \treturn 0;\n> @@ -143,9 +148,7 @@ void IPCUnixSocket::close()\n>  \tdelete notifier_;\n>  \tnotifier_ = nullptr;\n>\n> -\t::close(fd_);\n> -\n> -\tfd_ = -1;\n> +\tfd_.reset();\n>  \theaderReceived_ = false;\n>  }\n>\n> @@ -155,7 +158,7 @@ void IPCUnixSocket::close()\n>   */\n>  bool IPCUnixSocket::isBound() const\n>  {\n> -\treturn fd_ != -1;\n> +\treturn fd_.isValid();\n>  }\n>\n>  /**\n> @@ -182,7 +185,7 @@ int IPCUnixSocket::send(const Payload &payload)\n>  \tif (!hdr.data && !hdr.fds)\n>  \t\treturn -EINVAL;\n>\n> -\tret = ::send(fd_, &hdr, sizeof(hdr), 0);\n> +\tret = ::send(fd_.get(), &hdr, sizeof(hdr), 0);\n>  \tif (ret < 0) {\n>  \t\tret = -errno;\n>  \t\tLOG(IPCUnixSocket, Error)\n> @@ -263,7 +266,7 @@ int IPCUnixSocket::sendData(const void *buffer, size_t length,\n>  \tif (fds)\n>  \t\tmemcpy(CMSG_DATA(cmsg), fds, num * sizeof(uint32_t));\n>\n> -\tif (sendmsg(fd_, &msg, 0) < 0) {\n> +\tif (sendmsg(fd_.get(), &msg, 0) < 0) {\n>  \t\tint ret = -errno;\n>  \t\tLOG(IPCUnixSocket, Error)\n>  \t\t\t<< \"Failed to sendmsg: \" << strerror(-ret);\n> @@ -297,7 +300,7 @@ int IPCUnixSocket::recvData(void *buffer, size_t length,\n>  \tmsg.msg_controllen = cmsg->cmsg_len;\n>  \tmsg.msg_flags = 0;\n>\n> -\tif (recvmsg(fd_, &msg, 0) < 0) {\n> +\tif (recvmsg(fd_.get(), &msg, 0) < 0) {\n>  \t\tint ret = -errno;\n>  \t\tif (ret != -EAGAIN)\n>  \t\t\tLOG(IPCUnixSocket, Error)\n> @@ -317,7 +320,7 @@ void IPCUnixSocket::dataNotifier()\n>\n>  \tif (!headerReceived_) {\n>  \t\t/* Receive the header. */\n> -\t\tret = ::recv(fd_, &header_, sizeof(header_), 0);\n> +\t\tret = ::recv(fd_.get(), &header_, sizeof(header_), 0);\n>  \t\tif (ret < 0) {\n>  \t\t\tret = -errno;\n>  \t\t\tLOG(IPCUnixSocket, Error)\n> @@ -333,7 +336,7 @@ void IPCUnixSocket::dataNotifier()\n>  \t * readyRead signal. The notifier will be reenabled by the receive()\n>  \t * function.\n>  \t */\n> -\tstruct pollfd fds = { fd_, POLLIN, 0 };\n> +\tstruct pollfd fds = { fd_.get(), POLLIN, 0 };\n>  \tret = poll(&fds, 1, 0);\n>  \tif (ret < 0)\n>  \t\treturn;\n> diff --git a/test/ipc/unixsocket.cpp b/test/ipc/unixsocket.cpp\n> index 7270bf4d2fe7..414f1bfc9d12 100644\n> --- a/test/ipc/unixsocket.cpp\n> +++ b/test/ipc/unixsocket.cpp\n> @@ -52,9 +52,9 @@ public:\n>  \t\tipc_.readyRead.connect(this, &UnixSocketTestSlave::readyRead);\n>  \t}\n>\n> -\tint run(int fd)\n> +\tint run(UniqueFD fd)\n>  \t{\n> -\t\tif (ipc_.bind(fd)) {\n> +\t\tif (ipc_.bind(std::move(fd))) {\n>  \t\t\tcerr << \"Failed to connect to IPC channel\" << endl;\n>  \t\t\treturn EXIT_FAILURE;\n>  \t\t}\n> @@ -360,11 +360,11 @@ protected:\n>\n>  \tint run()\n>  \t{\n> -\t\tint slavefd = ipc_.create();\n> -\t\tif (slavefd < 0)\n> +\t\tUniqueFD slavefd = ipc_.create();\n> +\t\tif (!slavefd.isValid())\n>  \t\t\treturn TestFail;\n>\n> -\t\tif (slaveStart(slavefd)) {\n> +\t\tif (slaveStart(slavefd.release())) {\n>  \t\t\tcerr << \"Failed to start slave\" << endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n> @@ -496,9 +496,9 @@ private:\n>  int main(int argc, char **argv)\n>  {\n>  \tif (argc == 2) {\n> -\t\tint ipcfd = std::stoi(argv[1]);\n> +\t\tUniqueFD ipcfd = UniqueFD(std::stoi(argv[1]));\n>  \t\tUnixSocketTestSlave slave;\n> -\t\treturn slave.run(ipcfd);\n> +\t\treturn slave.run(std::move(ipcfd));\n>  \t}\n>\n>  \treturn UnixSocketTest().execute();\n> diff --git a/test/ipc/unixsocket_ipc.cpp b/test/ipc/unixsocket_ipc.cpp\n> index ab5d25572d83..178ee1870056 100644\n> --- a/test/ipc/unixsocket_ipc.cpp\n> +++ b/test/ipc/unixsocket_ipc.cpp\n> @@ -49,9 +49,9 @@ public:\n>  \t\tipc_.readyRead.connect(this, &UnixSocketTestIPCSlave::readyRead);\n>  \t}\n>\n> -\tint run(int fd)\n> +\tint run(UniqueFD fd)\n>  \t{\n> -\t\tif (ipc_.bind(fd)) {\n> +\t\tif (ipc_.bind(std::move(fd))) {\n>  \t\t\tcerr << \"Failed to connect to IPC channel\" << endl;\n>  \t\t\treturn EXIT_FAILURE;\n>  \t\t}\n> @@ -222,9 +222,9 @@ int main(int argc, char **argv)\n>  {\n>  \t/* IPCPipeUnixSocket passes IPA module path in argv[1] */\n>  \tif (argc == 3) {\n> -\t\tint ipcfd = std::stoi(argv[2]);\n> +\t\tUniqueFD ipcfd = UniqueFD(std::stoi(argv[2]));\n>  \t\tUnixSocketTestIPCSlave slave;\n> -\t\treturn slave.run(ipcfd);\n> +\t\treturn slave.run(std::move(ipcfd));\n>  \t}\n>\n>  \treturn UnixSocketTestIPC().execute();\n> diff --git a/utils/ipc/generators/libcamera_templates/module_ipa_proxy_worker.cpp.tmpl b/utils/ipc/generators/libcamera_templates/module_ipa_proxy_worker.cpp.tmpl\n> index 764e7a3af63a..b65dc4cf31c5 100644\n> --- a/utils/ipc/generators/libcamera_templates/module_ipa_proxy_worker.cpp.tmpl\n> +++ b/utils/ipc/generators/libcamera_templates/module_ipa_proxy_worker.cpp.tmpl\n> @@ -27,8 +27,9 @@\n>  #include <libcamera/logging.h>\n>\n>  #include <libcamera/base/event_dispatcher.h>\n> -#include <libcamera/base/thread.h>\n>  #include <libcamera/base/log.h>\n> +#include <libcamera/base/thread.h>\n> +#include <libcamera/base/unique_fd.h>\n>\n>  #include \"libcamera/internal/camera_sensor.h\"\n>  #include \"libcamera/internal/control_serializer.h\"\n> @@ -122,9 +123,9 @@ public:\n>  \t\t}\n>  \t}\n>\n> -\tint init(std::unique_ptr<IPAModule> &ipam, int socketfd)\n> +\tint init(std::unique_ptr<IPAModule> &ipam, UniqueFD socketfd)\n>  \t{\n> -\t\tif (socket_.bind(socketfd) < 0) {\n> +\t\tif (socket_.bind(std::move(socketfd)) < 0) {\n>  \t\t\tLOG({{proxy_worker_name}}, Error)\n>  \t\t\t\t<< \"IPC socket binding failed\";\n>  \t\t\treturn EXIT_FAILURE;\n> @@ -203,10 +204,10 @@ int main(int argc, char **argv)\n>  \t\treturn EXIT_FAILURE;\n>  \t}\n>\n> -\tint fd = std::stoi(argv[2]);\n> +\tUniqueFD fd(std::stoi(argv[2]));\n>  \tLOG({{proxy_worker_name}}, Info)\n>  \t\t<< \"Starting worker for IPA module \" << argv[1]\n> -\t\t<< \" with IPC fd = \" << fd;\n> +\t\t<< \" with IPC fd = \" << fd.get();\n>\n>  \tstd::unique_ptr<IPAModule> ipam = std::make_unique<IPAModule>(argv[1]);\n>  \tif (!ipam->isValid() || !ipam->load()) {\n> @@ -228,7 +229,7 @@ int main(int argc, char **argv)\n>  \t}\n>\n>  \t{{proxy_worker_name}} proxyWorker;\n> -\tint ret = proxyWorker.init(ipam, fd);\n> +\tint ret = proxyWorker.init(ipam, std::move(fd));\n>  \tif (ret < 0) {\n>  \t\tLOG({{proxy_worker_name}}, Error)\n>  \t\t\t<< \"Failed to initialize proxy worker\";\n> --\n> Regards,\n>\n> Laurent Pinchart\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 3DA17BF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 30 Nov 2021 07:53:36 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 84CF2605B7;\n\tTue, 30 Nov 2021 08:53:35 +0100 (CET)","from relay10.mail.gandi.net (relay10.mail.gandi.net\n\t[217.70.178.230])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 21895604FC\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 30 Nov 2021 08:53:34 +0100 (CET)","(Authenticated sender: jacopo@jmondi.org)\n\tby relay10.mail.gandi.net (Postfix) with ESMTPSA id 8988624000A;\n\tTue, 30 Nov 2021 07:53:33 +0000 (UTC)"],"Date":"Tue, 30 Nov 2021 08:54:26 +0100","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Message-ID":"<20211130075426.xoyzmatab44hq3kz@uno.localdomain>","References":"<20211130033820.18235-1-laurent.pinchart@ideasonboard.com>\n\t<20211130033820.18235-11-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20211130033820.18235-11-laurent.pinchart@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v4 10/22] libcamera: ipc_unixsocket:\n\tUse UniqueFD for a file descriptor","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]