mirror of
https://github.com/lihop/godot-xterm.git
synced 2024-11-22 01:30:25 +01:00
Kill child process and close pty on exit
- Adds kill() method to LibuvUtils. - Adds close() method to Pipe.
This commit is contained in:
parent
55b0a0577d
commit
c81da3820b
10 changed files with 53 additions and 9 deletions
|
@ -88,5 +88,4 @@ func _input(event):
|
||||||
|
|
||||||
|
|
||||||
func _on_PTY_exited(exit_code: int, signum: int):
|
func _on_PTY_exited(exit_code: int, signum: int):
|
||||||
print("exit_code: ", exit_code, " signum: ", signum)
|
|
||||||
emit_signal("exited", exit_code, signum)
|
emit_signal("exited", exit_code, signum)
|
||||||
|
|
|
@ -9,6 +9,8 @@ void LibuvUtils::_register_methods() {
|
||||||
register_method("get_os_environ", &LibuvUtils::get_os_environ);
|
register_method("get_os_environ", &LibuvUtils::get_os_environ);
|
||||||
register_method("get_os_release", &LibuvUtils::get_os_release);
|
register_method("get_os_release", &LibuvUtils::get_os_release);
|
||||||
register_method("get_cwd", &LibuvUtils::get_cwd);
|
register_method("get_cwd", &LibuvUtils::get_cwd);
|
||||||
|
|
||||||
|
register_method("kill", &LibuvUtils::kill);
|
||||||
}
|
}
|
||||||
|
|
||||||
LibuvUtils::LibuvUtils() {}
|
LibuvUtils::LibuvUtils() {}
|
||||||
|
@ -61,6 +63,10 @@ String LibuvUtils::get_cwd() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
godot_error LibuvUtils::kill(int pid, int signum) {
|
||||||
|
RETURN_UV_ERR(uv_kill(pid, signum));
|
||||||
|
}
|
||||||
|
|
||||||
godot_error LibuvUtils::translate_uv_errno(int uv_err) {
|
godot_error LibuvUtils::translate_uv_errno(int uv_err) {
|
||||||
if (uv_err >= 0)
|
if (uv_err >= 0)
|
||||||
return GODOT_OK;
|
return GODOT_OK;
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
String(uv_strerror(uv_err)));
|
String(uv_strerror(uv_err)));
|
||||||
|
|
||||||
#define RETURN_UV_ERR(uv_err) \
|
#define RETURN_UV_ERR(uv_err) \
|
||||||
UV_ERR_PRINT(uv_err); \
|
if (uv_err < 0) { \
|
||||||
|
UV_ERR_PRINT(uv_err); \
|
||||||
|
} \
|
||||||
return LibuvUtils::translate_uv_errno(uv_err);
|
return LibuvUtils::translate_uv_errno(uv_err);
|
||||||
|
|
||||||
#define RETURN_IF_UV_ERR(uv_err) \
|
#define RETURN_IF_UV_ERR(uv_err) \
|
||||||
|
@ -34,6 +36,8 @@ public:
|
||||||
String get_os_release();
|
String get_os_release();
|
||||||
String get_cwd();
|
String get_cwd();
|
||||||
|
|
||||||
|
godot_error kill(int pid, int signum);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static godot_error translate_uv_errno(int uv_err);
|
static godot_error translate_uv_errno(int uv_err);
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,7 +31,7 @@ void Pipe::_register_methods() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Pipe::Pipe() {}
|
Pipe::Pipe() {}
|
||||||
Pipe::~Pipe() {}
|
Pipe::~Pipe() { close(); }
|
||||||
|
|
||||||
void Pipe::_init() {}
|
void Pipe::_init() {}
|
||||||
|
|
||||||
|
@ -39,6 +39,8 @@ void _poll_connection();
|
||||||
|
|
||||||
void _read_cb(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf);
|
void _read_cb(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf);
|
||||||
|
|
||||||
|
void _close_cb(uv_handle_t *handle);
|
||||||
|
|
||||||
void _write_cb(uv_write_t *req, int status);
|
void _write_cb(uv_write_t *req, int status);
|
||||||
|
|
||||||
void _alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
|
void _alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
|
||||||
|
@ -56,6 +58,11 @@ godot_error Pipe::open(int fd, bool ipc = false) {
|
||||||
return GODOT_OK;
|
return GODOT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Pipe::close() {
|
||||||
|
uv_close((uv_handle_t *)&handle, NULL);
|
||||||
|
uv_run(uv_default_loop(), UV_RUN_NOWAIT);
|
||||||
|
}
|
||||||
|
|
||||||
godot_error Pipe::write(String p_data) {
|
godot_error Pipe::write(String p_data) {
|
||||||
char *s = p_data.alloc_c_string();
|
char *s = p_data.alloc_c_string();
|
||||||
ULONG len = strlen(s);
|
ULONG len = strlen(s);
|
||||||
|
@ -88,10 +95,10 @@ void _read_cb(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf) {
|
||||||
switch (nread) {
|
switch (nread) {
|
||||||
case UV_EOF:
|
case UV_EOF:
|
||||||
// Normal after shell exits.
|
// Normal after shell exits.
|
||||||
return;
|
|
||||||
case UV_EIO:
|
case UV_EIO:
|
||||||
// Can happen when the process exits.
|
// Can happen when the process exits.
|
||||||
// As long as PTY has caught it, we should be fine.
|
// As long as PTY has caught it, we should be fine.
|
||||||
|
uv_read_stop(handle);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
UV_ERR_PRINT(nread);
|
UV_ERR_PRINT(nread);
|
||||||
|
|
|
@ -23,6 +23,7 @@ public:
|
||||||
void _init();
|
void _init();
|
||||||
|
|
||||||
godot_error open(int fd, bool ipc);
|
godot_error open(int fd, bool ipc);
|
||||||
|
void close();
|
||||||
int get_status();
|
int get_status();
|
||||||
|
|
||||||
godot_error write(String p_data);
|
godot_error write(String p_data);
|
||||||
|
|
|
@ -25,5 +25,9 @@ static func get_windows_build_number() -> int:
|
||||||
assert(false, "Not implemented.")
|
assert(false, "Not implemented.")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
static func kill(pid: int, signum: int):
|
||||||
|
if pid > 1:
|
||||||
|
return LibuvUtils.new().kill(pid, signum)
|
||||||
|
|
||||||
static func new():
|
static func new():
|
||||||
assert(false, "Abstract sealed (i.e. static) class should not be instantiated.")
|
assert(false, "Abstract sealed (i.e. static) class should not be instantiated.")
|
||||||
|
|
|
@ -212,8 +212,11 @@ func destroy() -> void:
|
||||||
# Kill the pty.
|
# Kill the pty.
|
||||||
# sigint: The signal to send. By default this is SIGHUP.
|
# sigint: The signal to send. By default this is SIGHUP.
|
||||||
# This is not supported on Windows.
|
# This is not supported on Windows.
|
||||||
func kill(sigint: int = Signal.SIGHUP) -> void:
|
func kill(signum: int = Signal.SIGHUP) -> void:
|
||||||
pass
|
if _pipe:
|
||||||
|
_pipe.close()
|
||||||
|
if pid > 0:
|
||||||
|
LibuvUtils.kill(pid, signum)
|
||||||
|
|
||||||
|
|
||||||
func fork(
|
func fork(
|
||||||
|
|
|
@ -42,7 +42,6 @@ func _resize(cols: int, rows: int) -> void:
|
||||||
|
|
||||||
func _fork_thread(args):
|
func _fork_thread(args):
|
||||||
var result = preload("./pty_unix.gdns").new().callv("fork", args)
|
var result = preload("./pty_unix.gdns").new().callv("fork", args)
|
||||||
print(result)
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,6 +87,8 @@ func fork(
|
||||||
status = STATUS_ERROR
|
status = STATUS_ERROR
|
||||||
return FAILED
|
return FAILED
|
||||||
|
|
||||||
|
pid = result[1].pid
|
||||||
|
|
||||||
_pipe = Pipe.new()
|
_pipe = Pipe.new()
|
||||||
_pipe.open(_fd)
|
_pipe.open(_fd)
|
||||||
|
|
||||||
|
@ -101,12 +102,20 @@ func open(cols: int = DEFAULT_COLS, rows: int = DEFAULT_ROWS) -> Array:
|
||||||
return PTYUnix.new().open(cols, rows)
|
return PTYUnix.new().open(cols, rows)
|
||||||
|
|
||||||
|
|
||||||
|
func _exit_tree():
|
||||||
|
_exit_cb = null
|
||||||
|
if pid > 1:
|
||||||
|
LibuvUtils.kill(pid, Signal.SIGHUP)
|
||||||
|
|
||||||
|
|
||||||
func _on_pipe_data_received(data):
|
func _on_pipe_data_received(data):
|
||||||
emit_signal("data_received", data)
|
emit_signal("data_received", data)
|
||||||
|
|
||||||
|
|
||||||
func _on_exit(exit_code: int, signum: int) -> void:
|
func _on_exit(exit_code: int, signum: int) -> void:
|
||||||
emit_signal("exited", exit_code, signum)
|
if is_instance_valid(self):
|
||||||
|
pid = -1
|
||||||
|
emit_signal("exited", exit_code, signum)
|
||||||
|
|
||||||
|
|
||||||
func _sanitize_env(env: Dictionary) -> Dictionary:
|
func _sanitize_env(env: Dictionary) -> Dictionary:
|
||||||
|
|
|
@ -20,5 +20,4 @@ script = ExtResource( 1 )
|
||||||
__meta__ = {
|
__meta__ = {
|
||||||
"_edit_use_anchors_": false
|
"_edit_use_anchors_": false
|
||||||
}
|
}
|
||||||
|
|
||||||
[connection signal="key_pressed" from="Terminal" to="." method="_on_Terminal_key_pressed"]
|
[connection signal="key_pressed" from="Terminal" to="." method="_on_Terminal_key_pressed"]
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
extends "res://addons/gut/test.gd"
|
extends "res://addons/gut/test.gd"
|
||||||
|
|
||||||
|
const LibuvUtils := preload("res://addons/godot_xterm/nodes/pty/libuv_utils.gd")
|
||||||
|
|
||||||
var pty: GDXterm.PTYUnix
|
var pty: GDXterm.PTYUnix
|
||||||
var helper: Helper
|
var helper: Helper
|
||||||
|
|
||||||
|
@ -51,6 +53,16 @@ func test_open_pty_has_correct_win_size():
|
||||||
assert_eq(winsize.rows, rows)
|
assert_eq(winsize.rows, rows)
|
||||||
|
|
||||||
|
|
||||||
|
func test_closes_pty_on_exit():
|
||||||
|
var num_pts = helper._get_pts().size()
|
||||||
|
pty.fork("sleep", ["1000"])
|
||||||
|
remove_child(pty)
|
||||||
|
pty.free()
|
||||||
|
yield(yield_for(1), YIELD)
|
||||||
|
var new_num_pts = helper._get_pts().size()
|
||||||
|
assert_eq(new_num_pts, num_pts)
|
||||||
|
|
||||||
|
|
||||||
class Helper:
|
class Helper:
|
||||||
static func _get_pts() -> Array:
|
static func _get_pts() -> Array:
|
||||||
assert(false, "Abstract method")
|
assert(false, "Abstract method")
|
||||||
|
|
Loading…
Reference in a new issue