diff --git a/src/_macosx.m b/src/_macosx.m
index 8d92b75f6bfe..e9677a40e6b5 100755
--- a/src/_macosx.m
+++ b/src/_macosx.m
@@ -41,6 +41,66 @@
 static bool keyChangeCapsLock = false;
 /* Keep track of the current mouse up/down state for open/closed cursor hand */
 static bool leftMouseGrabbing = false;
+/* Keep track of whether stdin has been received */
+static bool stdin_received = false;
+static bool stdin_sigint = false;
+// Global variable to store the original SIGINT handler
+static struct sigaction originalSigintAction = {0};
+
+// Signal handler for SIGINT, only sets a flag to exit the run loop
+static void handleSigint(int signal) {
+    stdin_sigint = true;
+}
+
+static int wait_for_stdin() {
+    @autoreleasepool {
+        stdin_received = false;
+        stdin_sigint = false;
+
+        // Set up a SIGINT handler to interrupt the event loop if ctrl+c comes in too
+        struct sigaction customAction = {0};
+        customAction.sa_handler = handleSigint;
+        // Set the new handler and store the old one
+        sigaction(SIGINT, &customAction, &originalSigintAction);
+
+        // Create an NSFileHandle for standard input
+        NSFileHandle *stdinHandle = [NSFileHandle fileHandleWithStandardInput];
+
+        // Register for data available notifications on standard input
+        [[NSNotificationCenter defaultCenter] addObserverForName: NSFileHandleDataAvailableNotification
+                                                          object: stdinHandle
+                                                           queue: [NSOperationQueue mainQueue] // Use the main queue
+                                                      usingBlock: ^(NSNotification *notification) {
+                                                                    // Mark that input has been received
+                                                                    stdin_received = true;
+                                                                    }
+        ];
+
+        // Wait in the background for anything that happens to stdin
+        [stdinHandle waitForDataInBackgroundAndNotify];
+
+        // continuously run an event loop until the stdin_received flag is set to exit
+        while (!stdin_received && !stdin_sigint) {
+            while (true) {
+                NSEvent *event = [NSApp nextEventMatchingMask: NSEventMaskAny
+                                                    untilDate: [NSDate distantPast]
+                                                       inMode: NSDefaultRunLoopMode
+                                                      dequeue: YES];
+                if (!event) { break; }
+                [NSApp sendEvent: event];
+            }
+            // We need to run the run loop for a short time to allow the
+            // events to be processed and keep flushing them while we wait for stdin
+            [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
+        }
+        // Remove the input handler as an observer
+        [[NSNotificationCenter defaultCenter] removeObserver: stdinHandle];
+
+        // Restore the original SIGINT handler upon exiting the function
+        sigaction(SIGINT, &originalSigintAction, NULL);
+        return 1;
+    }
+}
 
 /* ---------------------------- Cocoa classes ---------------------------- */
 
@@ -139,6 +199,9 @@ static void lazy_init(void) {
     NSApp = [NSApplication sharedApplication];
     [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
 
+    // Run our own event loop while waiting for stdin on the Python side
+    // this is needed to keep the application responsive while waiting for input
+    PyOS_InputHook = wait_for_stdin;
 }
 
 static PyObject*