From patchwork Fri Dec 20 14:55:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Vuillaumier X-Patchwork-Id: 22425 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id CD023C3272 for ; Fri, 20 Dec 2024 14:55:51 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B061568499; Fri, 20 Dec 2024 15:55:50 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=nxp.com header.i=@nxp.com header.b="Skd8dR7a"; dkim-atps=neutral Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on20621.outbound.protection.outlook.com [IPv6:2a01:111:f403:2613::621]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6503367F24 for ; Fri, 20 Dec 2024 15:55:49 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=NTAN/aQ6iOohH+NGqcrhAkSfh+/lgjfpkv4n9CemuQEPnO3C7Pr+CjviUlxWdwccjXd1lP78wCuDyizu3yfebwkn1qPwaDviAl+1yGfZla/w3WOzVulZpaJMMoWdXS+PQ0CK+7ygFvARWls84BcbzWew7RsfF/77AGBqaXo3L0KkQa6LSqBAyj8LJITb99Sysvjkn7aJ18zg0o5RNmKKYXsQerAk8y7uJunVZdtERd4HuuscKV3AjBt1eBt6BDrHCFyDNhWC5RO2tZxVjdRtx7pB1ybbhrdXZSbf6Y6tId4VLeAMWdvELz7zFHr7ktpertk1XNMPv/DPTu7a5ohbUA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=SHFG78aODsDRWyQz92uOVrJg6IRGX6Aj2c7TGPjglus=; b=QAgwV5MMZ1cnC0XTiAn6WC1jR6vVNheLPHVEBoddMIIa5hy9rJsq0TVHc7J9CF8uY0asSEP6VgQd7/YoDXm3mxIFErz7J2hzk0QdsE/6EfVDvi9VG1W5elGrC5aP0nGrOL5h5l0TyoKyOIw13fewYzBAMxitZPYliBFX21BYYggHVoLsvfgP9IeuoMmA1d9/A0CAw2kTCNmso7Wsqg5SUUBrgbAF/10mN1y+EnKF8kPBwT2863LrXbWlxk/adj6DdeK3jT0SPHA8UR0clBdmyrOPiXRdPh08dumtAru7aLaAt4Gr2J/Jw4Ad2hNsyCGpU9EVulu7vm9bdTjmtJgr2A== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nxp.com; dmarc=pass action=none header.from=nxp.com; dkim=pass header.d=nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=SHFG78aODsDRWyQz92uOVrJg6IRGX6Aj2c7TGPjglus=; b=Skd8dR7aEa8LlIgjGe5qDfOQiaXa3SemKsQIvVqxi7/WK0X5odsThMUjq5AuIeu7VhUKWRWFMYmxmnTcxytbSpM14FHdGIWQO+Zsz4HDI0SQfcwxF7Ru5hc4MwbQOfUiYXmH5t2K1BKKTIluJyXOR3Hn+tNXAxzvYZbP5i3xBVKnyirvFQCSEpA5fTNFPGspBln68T2Sn2w5pe43tnK9ILB0Gp3oe3azO/fXimpZcr7cAoRTYrJ1KbvB1+M7+Fei1NLq/V6DGe6bTZJc0xsuuDk/umzHtOBRd2nkDbUrY4M49j0BvmchSc/OTOSu4JJbpqnUgPC2kVXEVkDPhVAo8w== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from AM9PR04MB8147.eurprd04.prod.outlook.com (2603:10a6:20b:3e0::22) by AM8PR04MB7233.eurprd04.prod.outlook.com (2603:10a6:20b:1df::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8272.16; Fri, 20 Dec 2024 14:55:47 +0000 Received: from AM9PR04MB8147.eurprd04.prod.outlook.com ([fe80::eace:e980:28a4:ef8a]) by AM9PR04MB8147.eurprd04.prod.outlook.com ([fe80::eace:e980:28a4:ef8a%5]) with mapi id 15.20.8272.005; Fri, 20 Dec 2024 14:55:47 +0000 From: Julien Vuillaumier To: libcamera-devel@lists.libcamera.org Cc: Julien Vuillaumier Subject: [PATCH] libcamera: ipc_unixsocket: Fix sendSync() timeout and hang Date: Fri, 20 Dec 2024 15:55:56 +0100 Message-Id: <20241220145556.3011657-1-julien.vuillaumier@nxp.com> X-Mailer: git-send-email 2.34.1 X-ClientProxiedBy: AS4P250CA0028.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:5e3::16) To AM9PR04MB8147.eurprd04.prod.outlook.com (2603:10a6:20b:3e0::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: AM9PR04MB8147:EE_|AM8PR04MB7233:EE_ X-MS-Office365-Filtering-Correlation-Id: 5d31faf3-5e38-4c0b-0043-08dd2106632d X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|1800799024|376014|52116014|366016|38350700014; X-Microsoft-Antispam-Message-Info: BcT5FUt6mYf5WYOjJpxe/K4sQ503jdEb3ZJiWt57dxbYUFfi9IPKZHs7lZqoAjYaGvf8xJITs+Ea9RlraivT2si8WTgwj1gQWOPU5wPdBoo5iiKMFx31An0gNh/ji8fq2m1YHL8H6uP3iuYjYF04kR7uQ5cxDmivu6SGhaUsL93cnvOoe5Pw3z1xgByRQofNmO6xgWzSwDinTwQSrL/VAVT0FeWUIF22i1daaoB7+8sqWKeH6xSJCfxQOPqREn3LWdx38FH+JNH1fDt4b/k5WjwReT8d7EYErAexfjafv7FoHZAM6HWEUa2qwtHbCU4iciTGzz5bEZDn9rNojypBmdk31FRfJqW4tD1qDdeyz3HPPnacrzDPJEZ0ExK5/O3LwsAy2Aug/LODfnC+lLCgC7vcYiE39vUJN2kQ2n/7NpRdu5NCG0P3xYN0vCzBLaqXy0m8t4ljKxw6Wj+WotbR1OgR2OviuIZnibZvCjGlv9HwOmhJfPFmxAJvMTLLGAd+n4naJ4qWz8/FV7iX4L2M5F/4I+ijH6PtYqIEXIs1akphn3S7U6dDCAuSORLGUghFP9jYrzmuv5FRupt7/EnK2lJw0vDj/igWPkBxc7mm/CiPlpItApaRp/kcTse/Vzto3HlbnyTCOw/De9JYNI6RZue2v5jV6w8x1qvNmcagQn3D6SK3EZkR+H0o/IyKjqekXPxhSpBh2pflBH4cTQ40dMHJ+NMzF6TkKudiWxQBiGNejmV1KoYvv173A83V1wlTQ9f5/SVbWBySmKsnlgPxjNfg2X6DAFrc3oFcxA59Hq6XNDGbj3FTHQv4s0td4W4zvL8NYKOFJJDr7UhYc6PNk64ImTyXMwx+uEKVfJ/+PmoSNXzAR4+flKGIC1f4KqMFh+lyy1fnOhgtUwAhlHk8KYQENh138EfTwomGnTI8kCyjGpboZFr14xYrVCQIK91JbrROAe6OXiUXYaFktVgpqU5l6RkkX+J+sc1lzhbrBx81uwubtdpCYSSQ56ItMTpJQyUsKfq2Jz1GuYr817vcKYh4rByeudpIEQ6sXFca/folEMg0q6I3wOlebaZTUrbZK3J7GNgbOIezLfzm/9nC4w+KKcgEpmbt97FD5N/SL0y9zMvyh7HxpirHYbYxWPesKojo6PofaSvQWFAPFo8OeKyVgJkcLQ4LVGONwgvXuj+9TRpKPzGt3HHQwP+heKCyGgt9XC0hPByRd2n9uNJNYEKvm0+O6Wjqom05d5cqdWDgyebgHd2rTsuyKQ9BYsSX/I+VBxh3JbSszzNwFJojnSRtmKZRUwxhUNOMybRD5kc3mZEX7sAdLWeYiHRACey4DMDYheLE/LQjiRKaF/dNBRmnVFjcmQdnD5AeXZQ14lFqgduiWarhv7PtIuZ8iXMD5GFnLz58jHKHxDHnCpPP5huKFKbrum0yhQP6YcP3TjxnuilToTAZLupMmkFJlpiW X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:AM9PR04MB8147.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(1800799024)(376014)(52116014)(366016)(38350700014); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: cOX5512XW6N2EZQFaptfH6pEsvlhb6YXe/JIOJ4HI+MSsZnPWX/bdJp/oLwHaIap/xOopLOP8NRzE7p6XMr4XIJwy3dJ8BeMuK1YR4WtjGN3HCW0pwbO8c1/DlUgiWwbH83C9aqRvkCLrASN6KSODBxRkuYvltzZyLYMvM1SyD/fgLEWMoAK9OlpmIDQAKrkCyYiA4y4Zb0Mt89FTNXk0uY5n4EgtB4iWuDJuiup9vT8t+tXleZVvAdjtXB4v8DhF63DRUtCEwBeWt37GpqNDBw8puHEXuUCy68fCPLRWP6onX3EySyflOtOw8VlwjNY/rHkFHMFfW1mmQ3vigMXNEyEy9rJKRuqtGdFyBjvXUoN/5sBhSpQhil0lYAMiiCqK7kNjI0gPOoy5NfIVy4j6ugSONMd6Y8JkiBFcH0cYNVBJyG96PgTJqa8uKsek3ANa7/WvuxMe2Y/ALc+dsNY6cqvPGGYdsRUtz6yNLMB+fcawWBcvAYMal3+pFDXb9u9/i2awrgj86ePjmt37xRJMcUSDMPwHGQPrG5GC5lfeaqHEURH8Bs3Pu8MDZmk5LFgDm4PBIHvmoTAAnJVjMnYXrksSsTz0mMPqr2x52/7M1adQ1fk7sN3UJ+n6vBGWHb1yGkERqPI6MYrWel97w/KPfnKCmOkW7WKooVlBNu34d0kY3MwjIxchTQkYmoLtcWnrMiQClHitBaWsFcoTSX/PXNHLS1tf+dEE/bRHiAMGOgeiGllz/gPE5NqhXa1iy7cPBdH1s1KOV7abf+Kithv2i9stinV394hGdnVkXwjll6dygiPtqCA1vPI7qP76BPiCnrm8ElRAEWNxEaEgWGX6zJ0QDnXFenvDqJMe3W7pvDxfmaMFvW3NmhQ/0JpwJrcpRCEGYjQqAxJEXrNHhUDPt9I2cVk1HUltR2GdgdWjuUIPID/Z9jmCvXYmnU15+SJU6Q22UVSo8QT6py7ArSu8TJ/J/Uk9sEqfWkevVIy3h2ekw3zzc9cPjtcVwxJU7lSJcHoyNVI/d10nOJVmLGDboviFOYCq0UanEik5crmLPvlBjk0LZ4z+c72jO+yxJlbb/mSRd3OpsqF4SczOS2Qsa8E/fzANWrIWGlmZ2knoJYBrto6qX8fhTOob/E/GFzVnyGU3QP8oifHc8yXz92xjrDsFyYsFZYTpzAE9jliP3vq0IACXwO7Sy/onnb3KleUAotppkMIc0h8wAbnsB8iuWHyBVl9a1zBBpIvm2nVilW+xTJx6JnKYq/XvMIxKQFTlQh/m/1eMBtHqu1py4zeKFLuWJWx9mUHa3YnQ+UgsKujPR3y4NMHcbD5lZOq26t8BeDkSHq+Ip1VF4kIgq/gD8IlknvG2eUFDhvu8DrI9qYn2zE5YHDyh8EEM89nZHF3qRreNsP17VrIZUKbKptpPd6q5p63EFfSZyuKe66SMfZEwlRjXPkR7U5RhIhsia1OSErEaFRr2rQAGBJHbEpwnzmFn8rq/kS7e2o4C7wnsuPJFXPnSmxTBQIRcspT3ncuzgqLgFZjwrd6bsOYFh8Elfcxa+TEvB3ntemJvCDmhCVOT31tL4+NslOylsauaBckC+yCE8G91y3FwmvbVQo+ZQ== X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 5d31faf3-5e38-4c0b-0043-08dd2106632d X-MS-Exchange-CrossTenant-AuthSource: AM9PR04MB8147.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Dec 2024 14:55:47.5492 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: gJn/pb02YJig3BsgZfhUmJxa07pArSdoXnr2jr4FfE2D5G83VcORD+zAMkeq3+zo09/kXCRvYZN1sHurTGxsUDBhSNsS5yTe8+0uJMWkt9k= X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM8PR04MB7233 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Unix-socket based IPC sometimes times out or hangs, typically when multiple camera are stopped simulaneously. That specific case triggers the concurrent sending by each pipeline handler instance of a synchronous stop() message to its peer IPA process. There is a dedicated IPC socket per camera. Sockets payload receipt signals all run in the camera manager thread. To send a synchronous message to IPA, pipeline invokes from camera thread IPCPipeUnixSocket::sendSync(). This sends the message then blocks busy waiting for the peer acknowledgment. Such busy wait is done by blocking on event loop calling dispatchEvent(), until the ack condition is detected. One issue is that the socket receive slot readyRead() wakes up the blocked thread via libcamera::Message receipt. Even though such message resumes processEvents(), it may reblock immediately because readyRead() does not interrupt() explictly the dispatcher. Most of the time, an other pending event for the thread unblocks the event dispatcher and the ack condition is detected - in worst case the 2 sec timeout kicks in. Once unblocked, the dispatcher let the message acknowledgment to be detected and the sendSync() completes. The other issue is that in case of concurrent synchronous IPC messages sent by multiple pipeline handlers, there is a possible recursion of sendSync() / processEvents() nested in the camera thread stack. As commented in the source, that is a dangerous construct that can lead to a hang. The reason is that the last synchronous message sent is the deepest in the stack. It is also the one whose acknowledgment is being busy waited. However other pending synchronous messages may have been initiated before and are upper in the stack. If they timeout, the condition is not detected because of the stack recursion, as the thread is busy waiting for the last message to be acknowledged. This change implements a safer mechanism to handle the synchronous message sending, similar to the one used for non isolated IPA. The IPCUnixSocketWrapper class is introduced to handle the IPCUnixSocket receive signal in a dedicated thread. Doing so, the sending thread, when emiting a synchronous message, can be blocked without event dispatcher's processEvents() usage, which avoids the risky stack recursion. Fixes: 21f1b555b ("libcamera: Add IPCPipe implementation based on unix socket") Signed-off-by: Julien Vuillaumier --- .../libcamera/internal/ipc_pipe_unixsocket.h | 13 +- src/libcamera/ipc_pipe_unixsocket.cpp | 242 +++++++++++++----- 2 files changed, 178 insertions(+), 77 deletions(-) diff --git a/include/libcamera/internal/ipc_pipe_unixsocket.h b/include/libcamera/internal/ipc_pipe_unixsocket.h index 8c972613..280639d5 100644 --- a/include/libcamera/internal/ipc_pipe_unixsocket.h +++ b/include/libcamera/internal/ipc_pipe_unixsocket.h @@ -16,6 +16,7 @@ namespace libcamera { class Process; +class IPCUnixSocketWrapper; class IPCPipeUnixSocket : public IPCPipe { @@ -29,18 +30,8 @@ public: int sendAsync(const IPCMessage &data) override; private: - struct CallData { - IPCUnixSocket::Payload *response; - bool done; - }; - - void readyRead(); - int call(const IPCUnixSocket::Payload &message, - IPCUnixSocket::Payload *response, uint32_t seq); - std::unique_ptr proc_; - std::unique_ptr socket_; - std::map callData_; + std::unique_ptr socketWrap_; }; } /* namespace libcamera */ diff --git a/src/libcamera/ipc_pipe_unixsocket.cpp b/src/libcamera/ipc_pipe_unixsocket.cpp index 668ec73b..eb5408d4 100644 --- a/src/libcamera/ipc_pipe_unixsocket.cpp +++ b/src/libcamera/ipc_pipe_unixsocket.cpp @@ -9,10 +9,9 @@ #include -#include #include +#include #include -#include #include "libcamera/internal/ipc_pipe.h" #include "libcamera/internal/ipc_unixsocket.h" @@ -24,67 +23,161 @@ namespace libcamera { LOG_DECLARE_CATEGORY(IPCPipe) -IPCPipeUnixSocket::IPCPipeUnixSocket(const char *ipaModulePath, - const char *ipaProxyWorkerPath) - : IPCPipe() +class IPCUnixSocketWrapper : Thread { - std::vector fds; - std::vector args; - args.push_back(ipaModulePath); +public: + IPCUnixSocketWrapper(Signal *recv) + : recv_(recv), ready_(false), sendSyncPending_(false), + sendSyncCookie_(0) + { + start(); + } - socket_ = std::make_unique(); - UniqueFD fd = socket_->create(); - if (!fd.isValid()) { - LOG(IPCPipe, Error) << "Failed to create socket"; - return; + ~IPCUnixSocketWrapper() + { + exit(); + wait(); } - socket_->readyRead.connect(this, &IPCPipeUnixSocket::readyRead); - args.push_back(std::to_string(fd.get())); - fds.push_back(fd.get()); - proc_ = std::make_unique(); - int ret = proc_->start(ipaProxyWorkerPath, args, fds); - if (ret) { - LOG(IPCPipe, Error) - << "Failed to start proxy worker process"; - return; + void run() override + { + /* + * IPC socket construction and connection to its readyRead + * signal has to be done from the IPC thread so that the + * relevant Object instances (EventNotifier, slot) are bound to + * its context. + */ + init(); + exec(); + deinit(); } - connected_ = true; -} + int fd() { return fd_.get(); } + int sendSync(const IPCMessage &in, IPCMessage *out); + int sendAsync(const IPCMessage &data); + bool waitReady(); -IPCPipeUnixSocket::~IPCPipeUnixSocket() -{ -} +private: + void init(); + void deinit(); + void readyRead(); -int IPCPipeUnixSocket::sendSync(const IPCMessage &in, IPCMessage *out) + UniqueFD fd_; + Signal *recv_; + ConditionVariable cv_; + Mutex mutex_; + bool ready_; + bool sendSyncPending_; + uint32_t sendSyncCookie_; + IPCUnixSocket::Payload *sendSyncResponse_; + + /* Socket shall be constructed and destructed from IPC thread context */ + std::unique_ptr socket_; +}; + +int IPCUnixSocketWrapper::sendSync(const IPCMessage &in, IPCMessage *out) { + int ret; IPCUnixSocket::Payload response; - int ret = call(in.payload(), &response, in.header().cookie); + mutex_.lock(); + ASSERT(!sendSyncPending_); + sendSyncPending_ = true; + sendSyncCookie_ = in.header().cookie; + sendSyncResponse_ = &response; + mutex_.unlock(); + + ret = socket_->send(in.payload()); if (ret) { - LOG(IPCPipe, Error) << "Failed to call sync"; - return ret; + LOG(IPCPipe, Error) << "Failed to send sync message"; + goto cleanup; + } + + bool complete; + { + MutexLocker locker(mutex_); + auto syncComplete = ([&]() { + return sendSyncPending_ == false; + }); + complete = cv_.wait_for(locker, 1000ms, syncComplete); + } + + if (!complete) { + LOG(IPCPipe, Error) << "Timeout sending sync message"; + ret = -ETIMEDOUT; + goto cleanup; } if (out) *out = IPCMessage(response); return 0; + +cleanup: + mutex_.lock(); + sendSyncPending_ = false; + mutex_.unlock(); + + return ret; } -int IPCPipeUnixSocket::sendAsync(const IPCMessage &data) +int IPCUnixSocketWrapper::sendAsync(const IPCMessage &data) { - int ret = socket_->send(data.payload()); - if (ret) { - LOG(IPCPipe, Error) << "Failed to call async"; - return ret; + int ret; + ret = socket_->send(data.payload()); + if (ret) + LOG(IPCPipe, Error) << "Failed to send sync message"; + return ret; +} + +bool IPCUnixSocketWrapper::waitReady() +{ + bool ready; + { + MutexLocker locker(mutex_); + auto isReady = ([&]() { + return ready_; + }); + ready = cv_.wait_for(locker, 1000ms, isReady); } - return 0; + return ready; +} + +void IPCUnixSocketWrapper::init() +{ + /* Init is to be done from the IPC thread context */ + ASSERT(Thread::current() == this); + + socket_ = std::make_unique(); + fd_ = socket_->create(); + if (!fd_.isValid()) { + LOG(IPCPipe, Error) << "Failed to create socket"; + return; + } + + socket_->readyRead.connect(this, &IPCUnixSocketWrapper::readyRead); + + mutex_.lock(); + ready_ = true; + mutex_.unlock(); + cv_.notify_one(); } -void IPCPipeUnixSocket::readyRead() +void IPCUnixSocketWrapper::deinit() +{ + /* Deinit is to be done from the IPC thread context */ + ASSERT(Thread::current() == this); + + socket_->readyRead.disconnect(this); + socket_.reset(); + + mutex_.lock(); + ready_ = false; + mutex_.unlock(); +} + +void IPCUnixSocketWrapper::readyRead() { IPCUnixSocket::Payload payload; int ret = socket_->receive(&payload); @@ -93,55 +186,72 @@ void IPCPipeUnixSocket::readyRead() return; } - /* \todo Use span to avoid the double copy when callData is found. */ if (payload.data.size() < sizeof(IPCMessage::Header)) { LOG(IPCPipe, Error) << "Not enough data received"; return; } - IPCMessage ipcMessage(payload); + const IPCMessage::Header *header = + reinterpret_cast(payload.data.data()); + bool syncComplete = false; + mutex_.lock(); + if (sendSyncPending_ && sendSyncCookie_ == header->cookie) { + syncComplete = true; + sendSyncPending_ = false; + *sendSyncResponse_ = std::move(payload); + } + mutex_.unlock(); - auto callData = callData_.find(ipcMessage.header().cookie); - if (callData != callData_.end()) { - *callData->second.response = std::move(payload); - callData->second.done = true; + if (syncComplete) { + cv_.notify_one(); return; } /* Received unexpected data, this means it's a call from the IPA. */ - recv.emit(ipcMessage); + IPCMessage ipcMessage(payload); + recv_->emit(ipcMessage); } -int IPCPipeUnixSocket::call(const IPCUnixSocket::Payload &message, - IPCUnixSocket::Payload *response, uint32_t cookie) +IPCPipeUnixSocket::IPCPipeUnixSocket(const char *ipaModulePath, + const char *ipaProxyWorkerPath) + : IPCPipe() { - Timer timeout; - int ret; + socketWrap_ = std::make_unique(&recv); + if (!socketWrap_->waitReady()) { + LOG(IPCPipe, Error) << "Failed to create socket"; + return; + } + int fd = socketWrap_->fd(); - const auto result = callData_.insert({ cookie, { response, false } }); - const auto &iter = result.first; + std::vector fds; + std::vector args; + args.push_back(ipaModulePath); + args.push_back(std::to_string(fd)); + fds.push_back(fd); - ret = socket_->send(message); + proc_ = std::make_unique(); + int ret = proc_->start(ipaProxyWorkerPath, args, fds); if (ret) { - callData_.erase(iter); - return ret; + LOG(IPCPipe, Error) + << "Failed to start proxy worker process"; + return; } - /* \todo Make this less dangerous, see IPCPipe::sendSync() */ - timeout.start(2000ms); - while (!iter->second.done) { - if (!timeout.isRunning()) { - LOG(IPCPipe, Error) << "Call timeout!"; - callData_.erase(iter); - return -ETIMEDOUT; - } + connected_ = true; +} - Thread::current()->eventDispatcher()->processEvents(); - } +IPCPipeUnixSocket::~IPCPipeUnixSocket() +{ +} - callData_.erase(iter); +int IPCPipeUnixSocket::sendSync(const IPCMessage &in, IPCMessage *out) +{ + return socketWrap_->sendSync(in, out); +} - return 0; +int IPCPipeUnixSocket::sendAsync(const IPCMessage &data) +{ + return socketWrap_->sendAsync(data); } } /* namespace libcamera */