diff Mac/Python/macglue.c @ 20949:d27ce8fe43f8 legacy-trunk

Fixed various problems with command-dot handling (some very old): - Don't scan for cmd-. unless in the foreground - Scan before switching out to other processes, not after - don't scan if SchedParams.check_interrupt is false (!) - But: do scan if we're blocked on I/O One problem remains: in the last case KeyboardInterrupt is raised too late.
author Jack Jansen <jack.jansen@cwi.nl>
date Sat, 10 Nov 2001 00:41:43 +0000
parents 6f259f7bbed8
children ed3dce17fc79
line wrap: on
line diff
--- a/Mac/Python/macglue.c	Fri Nov 09 23:34:26 2001 +0000
+++ b/Mac/Python/macglue.c	Sat Nov 10 00:41:43 2001 +0000
@@ -298,12 +298,21 @@
 		SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
 #endif
 
-	if (interrupted) return -1;
 
 	if ( msg == SP_AUTO_SPIN )
 		maxsleep = 0;
-	if ( msg==SP_SLEEP||msg==SP_SELECT )
+	if ( msg==SP_SLEEP||msg==SP_SELECT ) {
 		maxsleep = arg;
+		/*
+		** We force-scan for interrupts. Not pretty, but otherwise
+		** a program may hang in select or sleep forever.
+		*/
+		scan_event_queue(1);
+	}
+	if (interrupted) {
+		interrupted = 0;
+		return -1;
+	}
 
 	PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
 
@@ -453,23 +462,43 @@
 {
 }
 
+/* Check whether we are in the foreground */
+static int
+PyMac_InForeground(void)
+{
+	static ProcessSerialNumber ours;
+	static inited;
+	ProcessSerialNumber curfg;
+	Boolean eq;
+	
+	if ( inited == 0 ) {
+		(void)GetCurrentProcess(&ours);
+		inited = 1;
+	}
+	if ( GetFrontProcess(&curfg) < 0 )
+		eq = 1;
+	else if ( SameProcess(&ours, &curfg, &eq) < 0 )
+		eq = 1;
+	return (int)eq;
+}
+
 /*
 ** This routine scans the event queue looking for cmd-.
-** This is the only way to get an interrupt under THINK (since it
-** doesn't do SIGINT handling), but is also used under MW, when
-** the full-fledged event loop is disabled. This way, we can at least
-** interrupt a runaway python program.
 */
 static void
-scan_event_queue(flush)
-	int flush;
+scan_event_queue(force)
+	int force;
 {
 #if !TARGET_API_MAC_OS8
+	if ( interrupted || (!schedparams.check_interrupt && !force) )
+		return;
 	if ( CheckEventQueueForUserCancel() )
 		interrupted = 1;
 #else
 	register EvQElPtr q;
 	
+	if ( interrupted || (!schedparams.check_interrupt && !force) || !PyMac_InForeground() )
+		return;
 	q = (EvQElPtr) LMGetEventQueue()->qHead;
 	
 	for (; q; q = (EvQElPtr)q->qLink) {
@@ -488,18 +517,22 @@
 int
 PyErr_CheckSignals()
 {
+	int xxx, xxx_old;
+	
 	if (schedparams.enabled) {
-		if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
-			if ( PyMac_Yield() < 0)
-				return -1;
-			schedparams.next_check = (unsigned long)LMGetTicks()
-					 + schedparams.check_interval;
+		if ( interrupted || (unsigned long)LMGetTicks() > schedparams.next_check ) {
+			scan_event_queue(0);
 			if (interrupted) {
-				scan_event_queue(1);	/* Eat events up to cmd-. */
 				interrupted = 0;
 				PyErr_SetNone(PyExc_KeyboardInterrupt);
 				return -1;
 			}
+			if ( PyMac_Yield() < 0)
+				return -1;
+			xxx = LMGetTicks();
+			xxx_old = schedparams.next_check;
+			schedparams.next_check = (unsigned long)LMGetTicks()
+					 + schedparams.check_interval;
 		}
 	}
 	return 0;
@@ -508,28 +541,11 @@
 int
 PyOS_InterruptOccurred()
 {
-	scan_event_queue(1);
-	return interrupted;
-}
-
-/* Check whether we are in the foreground */
-static int
-PyMac_InForeground(void)
-{
-	static ProcessSerialNumber ours;
-	static inited;
-	ProcessSerialNumber curfg;
-	Boolean eq;
-	
-	if ( inited == 0 ) {
-		(void)GetCurrentProcess(&ours);
-		inited = 1;
-	}
-	if ( GetFrontProcess(&curfg) < 0 )
-		eq = 1;
-	else if ( SameProcess(&ours, &curfg, &eq) < 0 )
-		eq = 1;
-	return (int)eq;
+	scan_event_queue(0);
+	if ( !interrupted )
+		return 0;
+	interrupted = 0;
+	return 1;
 }
 #endif
 
@@ -616,15 +632,6 @@
 	static int in_here = 0;
 	
 	in_here++;
-	/*
-	** First check for interrupts, if wanted.
-	** This sets a flag that will be picked up at an appropriate
-	** moment in the mainloop.
-	*/
-	if (schedparams.check_interrupt)
-		scan_event_queue(0);
-	
-	/* XXXX Implementing an idle routine goes here */
 		
 	/*
 	** Check which of the eventloop cases we have: