]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Merged revisions 71126 via svnmerge from
authorKurt B. Kaiser <kbk@shore.net>
Sat, 4 Apr 2009 21:07:39 +0000 (21:07 +0000)
committerKurt B. Kaiser <kbk@shore.net>
Sat, 4 Apr 2009 21:07:39 +0000 (21:07 +0000)
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r71126 | kurt.kaiser | 2009-04-04 03:03:48 -0400 (Sat, 04 Apr 2009) | 5 lines

  Allow multiple IDLE GUI/subprocess pairs to exist
  simultaneously. Thanks to David Scherer for suggesting
  the use of an ephemeral port for the GUI.
  Patch 1529142 Weeble.
........

Lib/idlelib/NEWS.txt
Lib/idlelib/PyShell.py
Lib/idlelib/rpc.py

index c76174e0314fdb97159b5cf1f64592d3b1cf6c9c..cfd9b6fb53ab4f8f42bd8737240cd14c162566d4 100644 (file)
@@ -3,6 +3,10 @@ What's New in IDLE 3.1a1?
 
 *Release date: XX-XXX-XXXX*
 
+- Allow multiple IDLE GUI/subprocess pairs to exist simultaneously. Thanks to
+  David Scherer for suggesting the use of an ephemeral port for the GUI.
+  Patch 1529142 Weeble.
+
 - Remove port spec from run.py and fix bug where subprocess fails to
   extract port from command line when warnings are present.
 
index b61297ba504f9b7f611a16bd9980176e7d6d738e..01360891c86603be1ca942d65bf79da1c06dff5b 100644 (file)
@@ -34,7 +34,8 @@ from idlelib import Debugger
 from idlelib import RemoteDebugger
 from idlelib import macosxSupport
 
-LOCALHOST = '127.0.0.1'
+HOST = '127.0.0.1' # python execution server on localhost loopback
+PORT = 0  # someday pass in host, port for remote debug capability
 
 try:
     from signal import SIGTERM
@@ -339,17 +340,21 @@ class ModifiedInterpreter(InteractiveInterpreter):
         InteractiveInterpreter.__init__(self, locals=locals)
         self.save_warnings_filters = None
         self.restarting = False
-        self.subprocess_arglist = self.build_subprocess_arglist()
+        self.subprocess_arglist = None
+        self.port = PORT
 
-    port = 8833
     rpcclt = None
     rpcpid = None
 
     def spawn_subprocess(self):
+        if self.subprocess_arglist == None:
+            self.subprocess_arglist = self.build_subprocess_arglist()
         args = self.subprocess_arglist
         self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
 
     def build_subprocess_arglist(self):
+        assert (self.port!=0), (
+            "Socket should have been assigned a port number.")
         w = ['-W' + s for s in sys.warnoptions]
         # Maybe IDLE is installed and is being accessed via sys.path,
         # or maybe it's not installed and the idle.py script is being
@@ -368,11 +373,8 @@ class ModifiedInterpreter(InteractiveInterpreter):
         return [decorated_exec] + w + ["-c", command, str(self.port)]
 
     def start_subprocess(self):
-        # spawning first avoids passing a listening socket to the subprocess
-        self.spawn_subprocess()
-        #time.sleep(20) # test to simulate GUI not accepting connection
-        addr = (LOCALHOST, self.port)
-        # Idle starts listening for connection on localhost
+        addr = (HOST, self.port)
+        # GUI makes several attempts to acquire socket, listens for connection
         for i in range(3):
             time.sleep(i)
             try:
@@ -383,6 +385,18 @@ class ModifiedInterpreter(InteractiveInterpreter):
         else:
             self.display_port_binding_error()
             return None
+        # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
+        self.port = self.rpcclt.listening_sock.getsockname()[1]
+        # if PORT was not 0, probably working with a remote execution server
+        if PORT != 0:
+            # To allow reconnection within the 2MSL wait (cf. Stevens TCP
+            # V1, 18.6),  set SO_REUSEADDR.  Note that this can be problematic
+            # on Windows since the implementation allows two active sockets on
+            # the same address!
+            self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
+                                           socket.SO_REUSEADDR, 1)
+        self.spawn_subprocess()
+        #time.sleep(20) # test to simulate GUI not accepting connection
         # Accept the connection from the Python execution server
         self.rpcclt.listening_sock.settimeout(10)
         try:
@@ -734,13 +748,12 @@ class ModifiedInterpreter(InteractiveInterpreter):
     def display_port_binding_error(self):
         tkMessageBox.showerror(
             "Port Binding Error",
-            "IDLE can't bind TCP/IP port 8833, which is necessary to "
-            "communicate with its Python execution server.  Either "
-            "no networking is installed on this computer or another "
-            "process (another IDLE?) is using the port.  Run IDLE with the -n "
-            "command line switch to start without a subprocess and refer to "
-            "Help/IDLE Help 'Running without a subprocess' for further "
-            "details.",
+            "IDLE can't bind to a TCP/IP port, which is necessary to "
+            "communicate with its Python execution server.  This might be "
+            "because no networking is installed on this computer.  "
+            "Run IDLE with the -n command line switch to start without a "
+            "subprocess and refer to Help/IDLE Help 'Running without a "
+            "subprocess' for further details.",
             master=self.tkconsole.text)
 
     def display_no_subprocess_error(self):
@@ -1285,7 +1298,7 @@ def main():
     global flist, root, use_subprocess
 
     use_subprocess = True
-    enable_shell = False
+    enable_shell = True
     enable_edit = False
     debug = False
     cmd = None
@@ -1306,6 +1319,7 @@ def main():
             enable_shell = True
         if o == '-e':
             enable_edit = True
+            enable_shell = False
         if o == '-h':
             sys.stdout.write(usage_msg)
             sys.exit()
@@ -1356,7 +1370,6 @@ def main():
     edit_start = idleConf.GetOption('main', 'General',
                                     'editor-on-startup', type='bool')
     enable_edit = enable_edit or edit_start
-    enable_shell = enable_shell or not edit_start
     # start editor and/or shell windows:
     root = Tk(className="Idle")
 
index 5d5bcf7e02368e10261877167305b16780e360a6..d3fc3b0d2ac1f73514709ad55acde3f616bfec54 100644 (file)
@@ -518,8 +518,6 @@ class RPCClient(SocketIO):
 
     def __init__(self, address, family=socket.AF_INET, type=socket.SOCK_STREAM):
         self.listening_sock = socket.socket(family, type)
-        self.listening_sock.setsockopt(socket.SOL_SOCKET,
-                                       socket.SO_REUSEADDR, 1)
         self.listening_sock.bind(address)
         self.listening_sock.listen(1)