Skip to content

Commit 9f5deae

Browse files
committed
MAKE INTERRUPT WORK
1 parent b6a8229 commit 9f5deae

File tree

3 files changed

+28
-59
lines changed

3 files changed

+28
-59
lines changed

python_files/python_server.py

Lines changed: 15 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@
44
import json
55
import contextlib
66
import io
7-
from threading import Thread
87
import traceback
98

10-
is_interrupted = False
11-
EXECUTE_QUEUE = []
129
STDIN = sys.stdin
1310
STDOUT = sys.stdout
1411
STDERR = sys.stderr
@@ -36,29 +33,20 @@ def exec_function(user_input):
3633
return eval
3734

3835

39-
# have to run execute in different thread
40-
# interrupt will kill the thread.
36+
def execute(request, user_globals):
37+
str_output = CustomIO("<stdout>", encoding="utf-8")
38+
str_error = CustomIO("<stderr>", encoding="utf-8")
4139

40+
with redirect_io("stdout", str_output):
41+
with redirect_io("stderr", str_error):
42+
str_input = CustomIO("<stdin>", encoding="utf-8", newline="\n")
43+
with redirect_io("stdin", str_input):
44+
user_output_globals = exec_user_input(request["params"], user_globals)
45+
send_response(str_output.get_value(), request["id"])
46+
user_globals.update(user_output_globals)
4247

43-
def execute():
44-
while EXECUTE_QUEUE:
45-
request = EXECUTE_QUEUE.pop(0)
4648

47-
str_output = CustomIO("<stdout>", encoding="utf-8")
48-
str_error = CustomIO("<stderr>", encoding="utf-8")
49-
50-
with redirect_io("stdout", str_output):
51-
with redirect_io("stderr", str_error):
52-
str_input = CustomIO("<stdin>", encoding="utf-8", newline="\n")
53-
with redirect_io("stdin", str_input):
54-
user_output_globals = exec_user_input(
55-
request["id"], request["params"], user_globals
56-
)
57-
send_response(str_output.get_value(), request["id"])
58-
user_globals.update(user_output_globals)
59-
60-
61-
def exec_user_input(request_id, user_input, user_globals):
49+
def exec_user_input(user_input, user_globals):
6250
# have to do redirection
6351
user_input = user_input[0] if isinstance(user_input, list) else user_input
6452
user_globals = user_globals.copy()
@@ -68,6 +56,8 @@ def exec_user_input(request_id, user_input, user_globals):
6856
retval = callable(user_input, user_globals)
6957
if retval is not None:
7058
print(retval)
59+
except KeyboardInterrupt:
60+
print(traceback.format_exc())
7161
except Exception:
7262
print(traceback.format_exc())
7363
return user_globals
@@ -111,41 +101,22 @@ def get_headers():
111101
return headers
112102

113103

114-
# execute_queue.append({"id": 1, "params": "print('hello')"})
115-
116104
if __name__ == "__main__":
117105
user_globals = {}
118-
thread = None
119106

120107
while not STDIN.closed:
121108
try:
122109
headers = get_headers()
123110
content_length = int(headers.get("Content-Length", 0))
124-
# just one execute thread
125-
# queue execute items on that thread
111+
126112
if content_length:
127113
request_text = STDIN.read(content_length) # make sure Im getting right content
128114
request_json = json.loads(request_text)
129115
if request_json["method"] == "execute":
130-
EXECUTE_QUEUE.append(request_json)
131-
if thread is None or not thread.is_alive():
132-
thread = Thread(target=execute)
133-
thread.start()
134-
# execute_queue.append(request_json) # instead of directly calling execute, create another thread and run execute inside that thread
135-
elif request_json["method"] == "interrupt":
136-
# kill 'thread'
137-
# thread._stop() # THIS IS NOT WORKING
138-
139-
# set thread as empty
140-
thread = None
141-
# clear execute queue
142-
EXECUTE_QUEUE.clear()
116+
execute(request_json, user_globals)
143117

144118
elif request_json["method"] == "exit":
145119
sys.exit(0)
146120

147121
except Exception as e:
148122
print_log(str(e))
149-
150-
151-
# problem is not able to send interrupt to right thread or kill the thread directly.

src/client/repl/pythonServer.ts

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,17 @@ import * as ch from 'child_process';
33
import * as rpc from 'vscode-jsonrpc/node';
44
import { Disposable } from 'vscode';
55
import { EXTENSION_ROOT_DIR } from '../constants';
6+
import { traceError, traceLog } from '../logging';
67

7-
// const SERVER_PATH = path.join(__dirname, '...', 'python_files', 'python_server.py');
88
const SERVER_PATH = path.join(EXTENSION_ROOT_DIR, 'python_files', 'python_server.py');
99

10-
// const SERVER_PATH = path.join(__dirname, '..', '..', '..', 'pythonFiles', 'python_server.py');
11-
1210
export interface PythonServer extends Disposable {
1311
execute(code: string): Promise<string>;
14-
interrupt(): Promise<void>;
12+
interrupt(): void;
1513
}
1614

1715
class PythonServerImpl implements Disposable {
18-
constructor(private connection: rpc.MessageConnection) {
16+
constructor(private connection: rpc.MessageConnection, private pythonServer: ch.ChildProcess) {
1917
this.initialize();
2018
}
2119

@@ -30,10 +28,10 @@ class PythonServerImpl implements Disposable {
3028
return this.connection.sendRequest('execute', code);
3129
}
3230

33-
public interrupt(): Promise<void> {
34-
// return this.connection.sendRequest('interrupt', 'interrupt');
35-
// pythonServer.kill('SIGINT');
36-
return this.connection.sendRequest('interrupt', 'blah');
31+
public interrupt(): void {
32+
if (this.pythonServer.kill('SIGINT')) {
33+
traceLog('Python server interrupted');
34+
}
3735
}
3836

3937
public dispose(): void {
@@ -46,17 +44,18 @@ export function createPythonServer(interpreter: string[]): PythonServer {
4644
const pythonServer = ch.spawn(interpreter[0], [...interpreter.slice(1), SERVER_PATH]);
4745

4846
pythonServer.stderr.on('data', (data) => {
49-
console.error(data.toString());
47+
traceError(data.toString());
5048
});
5149
pythonServer.on('exit', (code) => {
52-
console.error(`Python server exited with code ${code}`);
50+
traceError(`Python server exited with code ${code}`);
5351
});
5452
pythonServer.on('error', (err) => {
55-
console.error(err);
53+
traceError(err);
5654
});
5755
const connection = rpc.createMessageConnection(
5856
new rpc.StreamMessageReader(pythonServer.stdout),
5957
new rpc.StreamMessageWriter(pythonServer.stdin),
6058
);
61-
return new PythonServerImpl(connection);
59+
60+
return new PythonServerImpl(connection, pythonServer);
6261
}

src/client/repl/replController.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ export function createReplController(interpreterPath: string): vscode.NotebookCo
88
controller.supportsExecutionOrder = true;
99

1010
controller.description = 'Python REPL';
11-
// let isInterrupted = false;
11+
1212
controller.interruptHandler = async () => {
13-
// isInterrupted = true;
1413
server.interrupt();
1514
};
1615

0 commit comments

Comments
 (0)