summaryrefslogtreecommitdiffstats
path: root/Lib/idlelib/run.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/idlelib/run.py')
-rw-r--r--Lib/idlelib/run.py81
1 files changed, 72 insertions, 9 deletions
diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py
index d79f3d7..497cbbd 100644
--- a/Lib/idlelib/run.py
+++ b/Lib/idlelib/run.py
@@ -2,6 +2,8 @@ import sys
import time
import socket
import traceback
+import threading
+import Queue
import boolcheck
@@ -10,9 +12,20 @@ import RemoteDebugger
import RemoteObjectBrowser
import StackViewer
import rpc
+import interrupt
import __main__
+# Thread shared globals: Establish a queue between a subthread (which handles
+# the socket) and the main thread (which runs user code), plus global
+# completion and exit flags:
+
+server = None # RPCServer instance
+queue = Queue.Queue(0)
+execution_finished = False
+exit_requested = False
+
+
def main():
"""Start the Python execution server in a subprocess
@@ -20,7 +33,7 @@ def main():
MyHandler, which inherits register/unregister methods from RPCHandler via
the mix-in class SocketIO.
- When the RPCServer svr is instantiated, the TCPServer initialization
+ When the RPCServer 'server' is instantiated, the TCPServer initialization
creates an instance of run.MyHandler and calls its handle() method.
handle() instantiates a run.Executive object, passing it a reference to the
MyHandler object. That reference is saved as attribute rpchandler of the
@@ -31,15 +44,35 @@ def main():
register and unregister themselves.
"""
+ global queue, execution_finished, exit_requested
+
port = 8833
if sys.argv[1:]:
port = int(sys.argv[1])
sys.argv[:] = [""]
- addr = ("localhost", port)
+ sockthread = threading.Thread(target=manage_socket,
+ name='SockThread',
+ args=(('localhost', port),))
+ sockthread.setDaemon(True)
+ sockthread.start()
+ while 1:
+ try:
+ if exit_requested:
+ sys.exit()
+ # XXX KBK 22Mar03 eventually check queue here!
+ pass
+ time.sleep(0.05)
+ except KeyboardInterrupt:
+ ##execution_finished = True
+ continue
+
+def manage_socket(address):
+ global server, exit_requested
+
for i in range(6):
time.sleep(i)
try:
- svr = rpc.RPCServer(addr, MyHandler)
+ server = rpc.RPCServer(address, MyHandler)
break
except socket.error, err:
if i < 3:
@@ -49,18 +82,21 @@ def main():
+ err[1] + ", retrying...."
else:
print>>sys.__stderr__, "\nConnection to Idle failed, exiting."
- sys.exit()
- svr.handle_request() # A single request only
+ exit_requested = True
+ server.handle_request() # A single request only
+
class MyHandler(rpc.RPCHandler):
def handle(self):
+ """Override base method"""
executive = Executive(self)
self.register("exec", executive)
sys.stdin = self.get_remote_proxy("stdin")
sys.stdout = self.get_remote_proxy("stdout")
sys.stderr = self.get_remote_proxy("stderr")
- rpc.RPCHandler.handle(self)
+ rpc.RPCHandler.getresponse(self, myseq=None, wait=0.5)
+
class Executive:
@@ -70,6 +106,25 @@ class Executive:
self.calltip = CallTips.CallTips()
def runcode(self, code):
+ global queue, execution_finished
+
+ execution_finished = False
+ queue.put(code)
+ # dequeue and run in subthread
+ self.runcode_from_queue()
+ while not execution_finished:
+ time.sleep(0.05)
+
+ def runcode_from_queue(self):
+ global queue, execution_finished
+
+ # poll until queue has code object, using threads, just block?
+ while True:
+ try:
+ code = queue.get(0)
+ break
+ except Queue.Empty:
+ time.sleep(0.05)
try:
exec code in self.locals
except:
@@ -85,7 +140,10 @@ class Executive:
lines = traceback.format_exception_only(typ, val)
for line in lines:
print>>efile, line,
- self.flush_stdout()
+ execution_finished = True
+ else:
+ self.flush_stdout()
+ execution_finished = True
def flush_stdout(self):
try:
@@ -126,9 +184,14 @@ class Executive:
tb[i] = fn, ln, nm, line
def interrupt_the_server(self):
- # XXX KBK 05Feb03 Windows requires this be done with messages and
- # threads....
self.rpchandler.interrupted = True
+ ##print>>sys.__stderr__, "** Interrupt main!"
+ interrupt.interrupt_main()
+
+ def shutdown_the_server(self):
+ global exit_requested
+
+ exit_requested = True
def start_the_debugger(self, gui_adap_oid):
return RemoteDebugger.start_debugger(self.rpchandler, gui_adap_oid)