mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Merged revisions 71126 via svnmerge from
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. ........
This commit is contained in:
		
							parent
							
								
									88f1435439
								
							
						
					
					
						commit
						e866c81d37
					
				
					 3 changed files with 34 additions and 19 deletions
				
			
		|  | @ -3,6 +3,10 @@ What's New in IDLE 3.1a1? | ||||||
| 
 | 
 | ||||||
| *Release date: XX-XXX-XXXX* | *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 | - Remove port spec from run.py and fix bug where subprocess fails to | ||||||
|   extract port from command line when warnings are present. |   extract port from command line when warnings are present. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -34,7 +34,8 @@ | ||||||
| from idlelib import RemoteDebugger | from idlelib import RemoteDebugger | ||||||
| from idlelib import macosxSupport | 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: | try: | ||||||
|     from signal import SIGTERM |     from signal import SIGTERM | ||||||
|  | @ -339,17 +340,21 @@ def __init__(self, tkconsole): | ||||||
|         InteractiveInterpreter.__init__(self, locals=locals) |         InteractiveInterpreter.__init__(self, locals=locals) | ||||||
|         self.save_warnings_filters = None |         self.save_warnings_filters = None | ||||||
|         self.restarting = False |         self.restarting = False | ||||||
|         self.subprocess_arglist = self.build_subprocess_arglist() |         self.subprocess_arglist = None | ||||||
|  |         self.port = PORT | ||||||
| 
 | 
 | ||||||
|     port = 8833 |  | ||||||
|     rpcclt = None |     rpcclt = None | ||||||
|     rpcpid = None |     rpcpid = None | ||||||
| 
 | 
 | ||||||
|     def spawn_subprocess(self): |     def spawn_subprocess(self): | ||||||
|  |         if self.subprocess_arglist == None: | ||||||
|  |             self.subprocess_arglist = self.build_subprocess_arglist() | ||||||
|         args = self.subprocess_arglist |         args = self.subprocess_arglist | ||||||
|         self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args) |         self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args) | ||||||
| 
 | 
 | ||||||
|     def build_subprocess_arglist(self): |     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] |         w = ['-W' + s for s in sys.warnoptions] | ||||||
|         # Maybe IDLE is installed and is being accessed via sys.path, |         # Maybe IDLE is installed and is being accessed via sys.path, | ||||||
|         # or maybe it's not installed and the idle.py script is being |         # or maybe it's not installed and the idle.py script is being | ||||||
|  | @ -368,11 +373,8 @@ def build_subprocess_arglist(self): | ||||||
|         return [decorated_exec] + w + ["-c", command, str(self.port)] |         return [decorated_exec] + w + ["-c", command, str(self.port)] | ||||||
| 
 | 
 | ||||||
|     def start_subprocess(self): |     def start_subprocess(self): | ||||||
|         # spawning first avoids passing a listening socket to the subprocess |         addr = (HOST, self.port) | ||||||
|         self.spawn_subprocess() |         # GUI makes several attempts to acquire socket, listens for connection | ||||||
|         #time.sleep(20) # test to simulate GUI not accepting connection |  | ||||||
|         addr = (LOCALHOST, self.port) |  | ||||||
|         # Idle starts listening for connection on localhost |  | ||||||
|         for i in range(3): |         for i in range(3): | ||||||
|             time.sleep(i) |             time.sleep(i) | ||||||
|             try: |             try: | ||||||
|  | @ -383,6 +385,18 @@ def start_subprocess(self): | ||||||
|         else: |         else: | ||||||
|             self.display_port_binding_error() |             self.display_port_binding_error() | ||||||
|             return None |             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 |         # Accept the connection from the Python execution server | ||||||
|         self.rpcclt.listening_sock.settimeout(10) |         self.rpcclt.listening_sock.settimeout(10) | ||||||
|         try: |         try: | ||||||
|  | @ -734,13 +748,12 @@ def write(self, s): | ||||||
|     def display_port_binding_error(self): |     def display_port_binding_error(self): | ||||||
|         tkMessageBox.showerror( |         tkMessageBox.showerror( | ||||||
|             "Port Binding Error", |             "Port Binding Error", | ||||||
|             "IDLE can't bind TCP/IP port 8833, which is necessary to " |             "IDLE can't bind to a TCP/IP port, which is necessary to " | ||||||
|             "communicate with its Python execution server.  Either " |             "communicate with its Python execution server.  This might be " | ||||||
|             "no networking is installed on this computer or another " |             "because no networking is installed on this computer.  " | ||||||
|             "process (another IDLE?) is using the port.  Run IDLE with the -n " |             "Run IDLE with the -n command line switch to start without a " | ||||||
|             "command line switch to start without a subprocess and refer to " |             "subprocess and refer to Help/IDLE Help 'Running without a " | ||||||
|             "Help/IDLE Help 'Running without a subprocess' for further " |             "subprocess' for further details.", | ||||||
|             "details.", |  | ||||||
|             master=self.tkconsole.text) |             master=self.tkconsole.text) | ||||||
| 
 | 
 | ||||||
|     def display_no_subprocess_error(self): |     def display_no_subprocess_error(self): | ||||||
|  | @ -1285,7 +1298,7 @@ def main(): | ||||||
|     global flist, root, use_subprocess |     global flist, root, use_subprocess | ||||||
| 
 | 
 | ||||||
|     use_subprocess = True |     use_subprocess = True | ||||||
|     enable_shell = False |     enable_shell = True | ||||||
|     enable_edit = False |     enable_edit = False | ||||||
|     debug = False |     debug = False | ||||||
|     cmd = None |     cmd = None | ||||||
|  | @ -1306,6 +1319,7 @@ def main(): | ||||||
|             enable_shell = True |             enable_shell = True | ||||||
|         if o == '-e': |         if o == '-e': | ||||||
|             enable_edit = True |             enable_edit = True | ||||||
|  |             enable_shell = False | ||||||
|         if o == '-h': |         if o == '-h': | ||||||
|             sys.stdout.write(usage_msg) |             sys.stdout.write(usage_msg) | ||||||
|             sys.exit() |             sys.exit() | ||||||
|  | @ -1356,7 +1370,6 @@ def main(): | ||||||
|     edit_start = idleConf.GetOption('main', 'General', |     edit_start = idleConf.GetOption('main', 'General', | ||||||
|                                     'editor-on-startup', type='bool') |                                     'editor-on-startup', type='bool') | ||||||
|     enable_edit = enable_edit or edit_start |     enable_edit = enable_edit or edit_start | ||||||
|     enable_shell = enable_shell or not edit_start |  | ||||||
|     # start editor and/or shell windows: |     # start editor and/or shell windows: | ||||||
|     root = Tk(className="Idle") |     root = Tk(className="Idle") | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -518,8 +518,6 @@ class RPCClient(SocketIO): | ||||||
| 
 | 
 | ||||||
|     def __init__(self, address, family=socket.AF_INET, type=socket.SOCK_STREAM): |     def __init__(self, address, family=socket.AF_INET, type=socket.SOCK_STREAM): | ||||||
|         self.listening_sock = socket.socket(family, type) |         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.bind(address) | ||||||
|         self.listening_sock.listen(1) |         self.listening_sock.listen(1) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Kurt B. Kaiser
						Kurt B. Kaiser