Mercurial > cpython-lru_cache-weakref
diff Lib/idlelib/PyShell.py @ 29034:656493534cc7 legacy-trunk
1. Implement processing of user code in subprocess MainThread. Pass loop
is now interruptable on Windows.
2. Tweak signal.signal() wait parameters as called by various methods
to improve I/O response, especially on Windows.
3. Debugger is disabled at this check-in pending further development.
M NEWS.txt
M PyShell.py
M rpc.py
M run.py
| author | Kurt B. Kaiser <kbk@shore.net> |
|---|---|
| date | Thu, 08 May 2003 20:26:55 +0000 |
| parents | b23434211d01 |
| children | 92ebd3daf507 |
line wrap: on
line diff
--- a/Lib/idlelib/PyShell.py Thu May 08 18:13:59 2003 +0000 +++ b/Lib/idlelib/PyShell.py Thu May 08 20:26:55 2003 +0000 @@ -35,6 +35,11 @@ IDENTCHARS = string.ascii_letters + string.digits + "_" +try: + from signal import SIGTERM +except ImportError: + SIGTERM = 15 + # Change warnings module to write to sys.__stderr__ try: import warnings @@ -367,13 +372,8 @@ except: pass # Kill subprocess, spawn a new one, accept connection. - try: - self.interrupt_subprocess() - self.shutdown_subprocess() - self.rpcclt.close() - os.wait() - except: - pass + self.rpcclt.close() + self.unix_terminate() self.tkconsole.executing = False self.spawn_subprocess() self.rpcclt.accept() @@ -391,42 +391,31 @@ # reload remote debugger breakpoints for all PyShellEditWindows debug.load_breakpoints() - def __signal_interrupt(self): - try: - from signal import SIGINT - except ImportError: - SIGINT = 2 - try: - os.kill(self.rpcpid, SIGINT) - except OSError: # subprocess may have already exited - pass - def __request_interrupt(self): - try: - self.rpcclt.asynccall("exec", "interrupt_the_server", (), {}) - except: - pass + self.rpcclt.remotecall("exec", "interrupt_the_server", (), {}) def interrupt_subprocess(self): - # XXX KBK 22Mar03 Use interrupt message on all platforms for now. - # XXX if hasattr(os, "kill"): - if False: - self.__signal_interrupt() - else: - # Windows has no os.kill(), use an RPC message. - # This is async, must be done in a thread. - threading.Thread(target=self.__request_interrupt).start() + threading.Thread(target=self.__request_interrupt).start() + + def kill_subprocess(self): + self.rpcclt.close() + self.unix_terminate() + self.tkconsole.executing = False + self.rpcclt = None - def __request_shutdown(self): - try: - self.rpcclt.asynccall("exec", "shutdown_the_server", (), {}) - except: - pass - - def shutdown_subprocess(self): - t = threading.Thread(target=self.__request_shutdown) - t.start() - t.join() + def unix_terminate(self): + "UNIX: make sure subprocess is terminated and collect status" + if hasattr(os, 'kill'): + try: + os.kill(self.rpcpid, SIGTERM) + except OSError: + # process already terminated: + return + else: + try: + os.waitpid(self.rpcpid, 0) + except OSError: + return def transfer_path(self): self.runcommand("""if 1: @@ -445,21 +434,15 @@ if clt is None: return try: - response = clt.pollresponse(self.active_seq) - except (EOFError, IOError): - # lost connection: subprocess terminated itself, restart + response = clt.pollresponse(self.active_seq, wait=0.05) + 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 - try: - # stake any zombie before restarting - os.wait() - except (AttributeError, OSError): - pass self.restart_subprocess() self.tkconsole.endexecuting() - # Reschedule myself in 50 ms - self.tkconsole.text.after(50, self.poll_subprocess) if response: self.tkconsole.resetoutput() self.active_seq = None @@ -477,13 +460,8 @@ print >>console, errmsg, what # we received a response to the currently active seq number: self.tkconsole.endexecuting() - - def kill_subprocess(self): - clt = self.rpcclt - if clt is not None: - self.shutdown_subprocess() - clt.close() - self.rpcclt = None + # Reschedule myself in 50 ms + self.tkconsole.text.after(50, self.poll_subprocess) debugger = None @@ -495,7 +473,7 @@ def remote_stack_viewer(self): import RemoteObjectBrowser - oid = self.rpcclt.remotecall("exec", "stackviewer", ("flist",), {}) + oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {}) if oid is None: self.tkconsole.root.bell() return @@ -628,7 +606,7 @@ self.display_executing_dialog() return 0 if self.rpcclt: - self.rpcclt.remotecall("exec", "runcode", (code,), {}) + self.rpcclt.remotequeue("exec", "runcode", (code,), {}) else: exec code in self.locals return 1 @@ -645,7 +623,7 @@ self.tkconsole.beginexecuting() try: if not debugger and self.rpcclt is not None: - self.active_seq = self.rpcclt.asynccall("exec", "runcode", + self.active_seq = self.rpcclt.asyncqueue("exec", "runcode", (code,), {}) elif debugger: debugger.run(code, self.locals) @@ -712,7 +690,7 @@ text.bind("<<beginning-of-line>>", self.home_callback) text.bind("<<end-of-file>>", self.eof_callback) text.bind("<<open-stack-viewer>>", self.open_stack_viewer) - text.bind("<<toggle-debugger>>", self.toggle_debugger) + ##text.bind("<<toggle-debugger>>", self.toggle_debugger) text.bind("<<open-python-shell>>", self.flist.open_shell) text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer) text.bind("<<view-restart>>", self.view_restart_mark) @@ -799,13 +777,9 @@ "Helper for ModifiedInterpreter" self.resetoutput() self.executing = 1 - ##self._cancel_check = self.cancel_check - ##sys.settrace(self._cancel_check) def endexecuting(self): "Helper for ModifiedInterpreter" - ##sys.settrace(None) - ##self._cancel_check = None self.executing = 0 self.canceled = 0 self.showprompt() @@ -822,7 +796,6 @@ return "cancel" # interrupt the subprocess self.closing = True - self.cancel_callback() self.endexecuting() return EditorWindow.close(self) @@ -1017,23 +990,6 @@ line = line[:i] more = self.interp.runsource(line) - def cancel_check(self, frame, what, args, - dooneevent=tkinter.dooneevent, - dontwait=tkinter.DONT_WAIT): - # Hack -- use the debugger hooks to be able to handle events - # and interrupt execution at any time. - # This slows execution down quite a bit, so you may want to - # disable this (by not calling settrace() in beginexecuting() and - # endexecuting() for full-bore (uninterruptable) speed.) - # XXX This should become a user option. - if self.canceled: - return - dooneevent(dontwait) - if self.canceled: - self.canceled = 0 - raise KeyboardInterrupt - return self._cancel_check - def open_stack_viewer(self, event=None): if self.interp.rpcclt: return self.interp.remote_stack_viewer()
