From 7c4ddb59430df022841fa9c1bca02402f61dcd71 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max.kellermann@gmail.com>
Date: Thu, 30 Jan 2025 19:57:17 +0100
Subject: [PATCH] input/uring: initialize uring_input_queue lazily

The BlockingCall() in InitUringInputPlugin() did not work because the
EventThread was not yet started.  This was never noticed until commit
e309941646e which enabled `IORING_SETUP_SINGLE_ISSUER`, and suddenly
the kernel refused to accept io_uring_submit() calls from the
io_thread because io_uring_setup() had been called from the main
thread.
---
 src/input/plugins/UringInputPlugin.cxx | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/src/input/plugins/UringInputPlugin.cxx b/src/input/plugins/UringInputPlugin.cxx
index bea7c523b..f001c5775 100644
--- a/src/input/plugins/UringInputPlugin.cxx
+++ b/src/input/plugins/UringInputPlugin.cxx
@@ -33,6 +33,7 @@ static const size_t URING_RESUME_AT = 384 * 1024;
 
 static EventLoop *uring_input_event_loop;
 static Uring::Queue *uring_input_queue;
+static bool uring_input_initialized = false;
 
 class UringInputStream final : public AsyncInputStream, Uring::ReadHandler {
 	Uring::Queue &uring;
@@ -163,6 +164,16 @@ UringInputStream::OnReadError(int error) noexcept
 InputStreamPtr
 OpenUringInputStream(const char *path, Mutex &mutex)
 {
+	if (!uring_input_initialized) {
+		BlockingCall(*uring_input_event_loop, [](){
+			if (uring_input_initialized)
+				return;
+
+			uring_input_queue = uring_input_event_loop->GetUring();
+			uring_input_initialized = true;
+		});
+	}
+
 	if (uring_input_queue == nullptr)
 		return nullptr;
 
@@ -187,8 +198,4 @@ void
 InitUringInputPlugin(EventLoop &event_loop) noexcept
 {
 	uring_input_event_loop = &event_loop;
-
-	BlockingCall(event_loop, [](){
-		uring_input_queue = uring_input_event_loop->GetUring();
-	});
 }