]> granicus.if.org Git - python/commitdiff
1. Stake Freddy.
authorKurt B. Kaiser <kbk@shore.net>
Sat, 24 May 2003 20:59:15 +0000 (20:59 +0000)
committerKurt B. Kaiser <kbk@shore.net>
Sat, 24 May 2003 20:59:15 +0000 (20:59 +0000)
   e.g. further improve subprocess interrupt, exceptions, and termination.
2. Remove the workarounds in PyShell.py and ScriptBinding.py involving
   interrupting the subprocess prior to killing it, not necessary anymore.
3. Fix a bug introduced at PyShell Rev 1.66: was getting extra shell menu
   every time the shell window was recreated.

M PyShell.py
M ScriptBinding.py
M rpc.py
M run.py

Lib/idlelib/PyShell.py
Lib/idlelib/ScriptBinding.py
Lib/idlelib/rpc.py
Lib/idlelib/run.py

index dc47f07d32e1e2cddd5e58da9e47d67d5e3ab83e..cb38411a3b3611c1bc044200870a0a8c16592553 100644 (file)
@@ -296,6 +296,14 @@ class ModifiedUndoDelegator(UndoDelegator):
             pass
         UndoDelegator.delete(self, index1, index2)
 
+
+class MyRPCClient(rpc.RPCClient):
+
+    def handle_EOF(self):
+        "Override the base class - just re-raise EOFError"
+        raise EOFError
+
+    
 class ModifiedInterpreter(InteractiveInterpreter):
 
     def __init__(self, tkconsole):
@@ -329,7 +337,7 @@ class ModifiedInterpreter(InteractiveInterpreter):
         for i in range(3):
             time.sleep(i)
             try:
-                self.rpcclt = rpc.RPCClient(addr)
+                self.rpcclt = MyRPCClient(addr)
                 break
             except socket.error, err:
                 print>>sys.__stderr__,"IDLE socket error: " + err[1]\
@@ -426,9 +434,10 @@ class ModifiedInterpreter(InteractiveInterpreter):
         except (EOFError, IOError, KeyboardInterrupt):
             # lost connection or subprocess terminated itself, restart
             # [the KBI is from rpc.SocketIO.handle_EOF()]
+            if self.tkconsole.closing:
+                return
             response = None
             self.restart_subprocess()
-            self.tkconsole.endexecuting()
         if response:
             self.tkconsole.resetoutput()
             self.active_seq = None
@@ -673,7 +682,9 @@ class PyShell(OutputWindow):
 
     def __init__(self, flist=None):
         if use_subprocess:
-            self.menu_specs.insert(2, ("shell", "_Shell"))
+            ms = self.menu_specs
+            if ms[2][0] != "shell":
+                ms.insert(2, ("shell", "_Shell"))
         self.interp = ModifiedInterpreter(self)
         if flist is None:
             root = Tk()
@@ -793,15 +804,9 @@ class PyShell(OutputWindow):
                 parent=self.text)
             if response == False:
                 return "cancel"
-            # interrupt the subprocess
-            self.canceled = True
-            if use_subprocess:
-                self.interp.interrupt_subprocess()
-            return "cancel"
-        else:
-            self.closing = True
-            # Wait for poll_subprocess() rescheduling to stop
-            self.text.after(2 * self.pollinterval, self.close2)
+        self.closing = True
+        # Wait for poll_subprocess() rescheduling to stop
+        self.text.after(2 * self.pollinterval, self.close2)
 
     def close2(self):
         return EditorWindow.close(self)
@@ -885,7 +890,10 @@ class PyShell(OutputWindow):
         if self.reading:
             self.top.quit()
         elif (self.executing and self.interp.rpcclt):
-            self.interp.interrupt_subprocess()
+            if self.interp.getdebugger():
+                self.interp.restart_subprocess()
+            else:
+                self.interp.interrupt_subprocess()
         return "break"
 
     def eof_callback(self, event):
@@ -1021,16 +1029,7 @@ class PyShell(OutputWindow):
         self.text.see("restart")
 
     def restart_shell(self, event=None):
-        if self.executing:
-            self.cancel_callback()
-            # Wait for subprocess to interrupt and restart
-            # This can be a long time if shell is scrolling on a slow system
-            # XXX 14 May 03 KBK This delay (and one in ScriptBinding) could be
-            #     shorter if we didn't print the KeyboardInterrupt on
-            #     restarting while user code is running....
-            self.text.after(2000, self.interp.restart_subprocess)
-        else:
-            self.interp.restart_subprocess()
+        self.interp.restart_subprocess()
 
     def showprompt(self):
         self.resetoutput()
index 252526d5630434fbb02705393dd26efddc409dbf..b6d9da3ab3f6d42573335882fcc1227676190579 100644 (file)
@@ -125,17 +125,6 @@ class ScriptBinding:
         interp = shell.interp
         if PyShell.use_subprocess:
             shell.restart_shell()
-            if shell.executing:
-                delay = 2700
-            else:
-                delay = 500
-            # Wait for the interrupt and reset to finish
-            shell.text.after(delay, self.run_module_event2, interp,
-                             filename, code)
-        else:
-            self.run_module_event2(interp, filename, code)
-
-    def run_module_event2(self, interp, filename, code):
         # XXX Too often this discards arguments the user just set...
         interp.runcommand("""if 1:
             _filename = %s
index 8bb1aba2b6b55d38ae92ca01ac1f808a9dd0d2f5..658aaf37f5543720d2dd1d221a7042c769c8b0d2 100644 (file)
@@ -41,7 +41,6 @@ import copy_reg
 import types
 import marshal
 
-import interrupt
 
 def unpickle_code(ms):
     co = marshal.loads(ms)
@@ -327,12 +326,9 @@ class SocketIO:
         while len(s) > 0:
             try:
                 n = self.sock.send(s)
-            except AttributeError:
+            except (AttributeError, socket.error):
                 # socket was closed
                 raise IOError
-            except socket.error:
-                self.debug("putmessage:socketerror:pid:%s" % os.getpid())
-                os._exit(0)
             else:
                 s = s[n:]
 
@@ -471,7 +467,6 @@ class SocketIO:
             self.responses[key] = ('EOF', None)
             cv.notify()
             cv.release()
-        interrupt.interrupt_main()
         # call our (possibly overridden) exit function
         self.exithook()
 
index 98255c79ce8241f4c7002ae142fad7f3e00363b4..abc99697ef917dae4e9d21db84208152c6e151b3 100644 (file)
@@ -21,7 +21,8 @@ import __main__
 # the socket) and the main thread (which runs user code), plus global
 # completion and exit flags:
 
-exit_requested = False
+exit_now = False
+quitting = False
 
 def main():
     """Start the Python execution server in a subprocess
@@ -41,6 +42,8 @@ def main():
     register and unregister themselves.
 
     """
+    global exit_now
+    global quitting
     port = 8833
     if sys.argv[1:]:
         port = int(sys.argv[1])
@@ -52,8 +55,12 @@ def main():
     sockthread.start()
     while 1:
         try:
-            if exit_requested:
-                sys.exit(0)
+            if exit_now:
+                try:
+                    sys.exit(0)
+                except KeyboardInterrupt:
+                    # exiting but got an extra KBI? Try again!
+                    continue
             try:
                 seq, request = rpc.request_queue.get(0)
             except Queue.Empty:
@@ -63,17 +70,22 @@ def main():
             ret = method(*args, **kwargs)
             rpc.response_queue.put((seq, ret))
         except KeyboardInterrupt:
+            if quitting:
+                exit_now = True
             continue
         except SystemExit:
             raise
         except:
+            type, value, tb = sys.exc_info()
             try:
                 print_exception()
                 rpc.response_queue.put((seq, None))
             except:
-                traceback.print_exc(file=sys.__stderr__)
-                sys.exit(1.1)
-            continue
+                # Link didn't work, print same exception to __stderr__
+                traceback.print_exception(type, value, tb, file=sys.__stderr__)
+                sys.exit(0)
+            else:
+                continue
 
 def manage_socket(address):
     for i in range(6):
@@ -89,17 +101,17 @@ def manage_socket(address):
                                               + err[1] + ", retrying...."
     else:
         print>>sys.__stderr__, "\nConnection to Idle failed, exiting."
-        global exit_requested
-        exit_requested = True
+        global exit_now
+        exit_now = True
         return
     server.handle_request() # A single request only
 
 def print_exception():
     flush_stdout()
     efile = sys.stderr
-    typ, val, tb = info = sys.exc_info()
+    typ, val, tb = sys.exc_info()
     tbe = traceback.extract_tb(tb)
-    print >>efile, 'Traceback (most recent call last):'
+    print >>efile, '\nTraceback (most recent call last):'
     exclude = ("run.py", "rpc.py", "threading.py", "Queue.py",
                "RemoteDebugger.py", "bdb.py")
     cleanup_traceback(tbe, exclude)
@@ -161,8 +173,8 @@ class MyRPCServer(rpc.RPCServer):
         except SystemExit:
             raise
         except EOFError:
-            global exit_requested
-            exit_requested = True
+            global exit_now
+            exit_now = True
             interrupt.interrupt_main()
         except:
             erf = sys.__stderr__
@@ -174,7 +186,7 @@ class MyRPCServer(rpc.RPCServer):
             traceback.print_exc(file=erf)
             print>>erf, '\n*** Unrecoverable, server exiting!'
             print>>erf, '-'*40
-            os._exit(0)
+            sys.exit(0)
 
 
 class MyHandler(rpc.RPCHandler):
@@ -190,15 +202,18 @@ class MyHandler(rpc.RPCHandler):
 
     def exithook(self):
         "override SocketIO method - wait for MainThread to shut us down"
-        while 1: pass
+        time.sleep(10)
 
     def EOFhook(self):
         "Override SocketIO method - terminate wait on callback and exit thread"
-        global exit_requested
-        exit_requested = True
+        global quitting
+        quitting = True
+        interrupt.interrupt_main()
 
     def decode_interrupthook(self):
         "interrupt awakened thread"
+        global quitting
+        quitting = True
         interrupt.interrupt_main()
 
 
@@ -213,15 +228,10 @@ class Executive:
         try:
             exec code in self.locals
         except:
-            if exit_requested:
+            if quitting:
                 sys.exit(0)
-            try:
-                # even print a user code SystemExit exception, continue
-                print_exception()
-            except:
-                # link not working? 
-                traceback.print_exc(file=sys.__stderr__)
-                sys.exit(1.2)
+            # even print a user code SystemExit exception, continue
+            print_exception()
         else:
             flush_stdout()