Add run_async to shell, which should be more stable than the previous threading

This might fix the "random crash" problem?
This commit is contained in:
blinry 2020-11-02 13:13:04 +01:00
parent 53f60247f3
commit e220211140
4 changed files with 67 additions and 40 deletions

View file

@ -28,12 +28,18 @@ _global_script_classes=[ {
"class": "Shell", "class": "Shell",
"language": "GDScript", "language": "GDScript",
"path": "res://scenes/shell.gd" "path": "res://scenes/shell.gd"
}, {
"base": "Node",
"class": "ShellCommand",
"language": "GDScript",
"path": "res://scenes/shell_command.gd"
} ] } ]
_global_script_class_icons={ _global_script_class_icons={
"Chapter": "", "Chapter": "",
"Level": "", "Level": "",
"LevelRepo": "", "LevelRepo": "",
"Shell": "" "Shell": "",
"ShellCommand": ""
} }
[application] [application]

View file

@ -18,8 +18,30 @@ func cd(dir):
# Run a shell command given as a string. Run this if you're interested in the # Run a shell command given as a string. Run this if you're interested in the
# output of the command. # output of the command.
func run(command, crash_on_fail=true): func run(command, crash_on_fail=true):
var shell_command = ShellCommand.new()
shell_command.command = command
shell_command.crash_on_fail = crash_on_fail
run_async_thread(shell_command)
exit_code = shell_command.exit_code
return shell_command.output
func run_async(command, crash_on_fail=true):
var shell_command = ShellCommand.new()
shell_command.command = command
shell_command.crash_on_fail = crash_on_fail
var _thread = Thread.new()
_thread.start(self, "run_async_thread", shell_command)
return shell_command
func run_async_thread(shell_command):
var debug = false var debug = false
var command = shell_command.command
var crash_on_fail = shell_command.crash_on_fail
if debug: if debug:
print("$ %s" % command) print("$ %s" % command)
@ -64,8 +86,9 @@ func run(command, crash_on_fail=true):
if debug: if debug:
print(result["output"]) print(result["output"])
exit_code = result["exit_code"] shell_command.output = result["output"]
return result["output"] shell_command.exit_code = result["exit_code"]
shell_command.emit_signal("done")
func _shell_binary(): func _shell_binary():
if _os == "X11" or _os == "OSX": if _os == "X11" or _os == "OSX":
@ -75,25 +98,25 @@ func _shell_binary():
else: else:
helpers.crash("Unsupported OS: %s" % _os) helpers.crash("Unsupported OS: %s" % _os)
var _t #var _t
func run_async(command): #func run_async(command):
_t = Thread.new() # _t = Thread.new()
_t.start(self, "run_async_thread", command) # _t.start(self, "run_async_thread", command)
#
func run_async_thread(command): #func run_async_thread(command):
var port = 1000 + (randi() % 1000) # var port = 1000 + (randi() % 1000)
var s = TCP_Server.new() # var s = TCP_Server.new()
s.listen(port) # s.listen(port)
var _pid = OS.execute("ncat", ["127.0.0.1", str(port), "-c", command], false, [], true) # var _pid = OS.execute("ncat", ["127.0.0.1", str(port), "-c", command], false, [], true)
while not s.is_connection_available(): # while not s.is_connection_available():
pass # pass
var c = s.take_connection() # var c = s.take_connection()
while c.get_status() == StreamPeerTCP.STATUS_CONNECTED: # while c.get_status() == StreamPeerTCP.STATUS_CONNECTED:
read_from(c) # read_from(c)
OS.delay_msec(1000/30) # OS.delay_msec(1000/30)
read_from(c) # read_from(c)
c.disconnect_from_host() # c.disconnect_from_host()
s.stop() # s.stop()
func read_from(c): func read_from(c):
var total_available = c.get_available_bytes() var total_available = c.get_available_bytes()

9
scenes/shell_command.gd Normal file
View file

@ -0,0 +1,9 @@
extends Node
class_name ShellCommand
signal done
var command
var output
var exit_code
var crash_on_fail = true

View file

@ -2,8 +2,6 @@ extends Control
signal command_done signal command_done
var thread
var history_position = 0 var history_position = 0
var git_commands = ["add", "am", "archive", "bisect", "branch", "bundle", "checkout", "cherry-pick", "citool", "clean", "clone", "commit", "describe", "diff", "fetch", "format-patch", "gc", "gitk", "grep", "gui", "init", "log", "merge", "mv", "notes", "pull", "push", "range-diff", "rebase", "reset", "restore", "revert", "rm", "shortlog", "show", "sparse-checkout", "stash", "status", "submodule", "switch", "tag", "worktree", "config", "fast-export", "fast-import", "filter-branch", "mergetool", "pack-refs", "prune", "reflog", "remote", "repack", "replace", "annotate", "blame", "bugreport", "count-objects", "difftool", "fsck", "gitweb", "help", "instaweb", "merge-tree", "rerere", "show-branch", "verify-commit", "verify-tag", "whatchanged", "archimport", "cvsexportcommit", "cvsimport", "cvsserver", "imap-send", "p", "quiltimport", "request-pull", "send-email", "svn", "apply", "checkout-index", "commit-graph", "commit-tree", "hash-object", "index-pack", "merge-file", "merge-index", "mktag", "mktree", "multi-pack-index", "pack-objects", "prune-packed", "read-tree", "symbolic-ref", "unpack-objects", "update-index", "update-ref", "write-tree", "cat-file", "cherry", "diff-files", "diff-index", "diff-tree", "for-each-ref", "get-tar-commit-id", "ls-files", "ls-remote", "ls-tree", "merge-base", "name-rev", "pack-redundant", "rev-list", "rev-parse", "show-index", "show-ref", "unpack-file", "var", "verify-pack", "daemon", "fetch-pack", "http-backend", "send-pack", "update-server-info", "check-attr", "check-ignore", "check-mailmap", "check-ref-format", "column", "credential", "credential-cache", "credential-store", "fmt-merge-msg", "interpret-trailers", "mailinfo", "mailsplit", "merge-one-file", "patch-id", "sh-i", "sh-setup"] var git_commands = ["add", "am", "archive", "bisect", "branch", "bundle", "checkout", "cherry-pick", "citool", "clean", "clone", "commit", "describe", "diff", "fetch", "format-patch", "gc", "gitk", "grep", "gui", "init", "log", "merge", "mv", "notes", "pull", "push", "range-diff", "rebase", "reset", "restore", "revert", "rm", "shortlog", "show", "sparse-checkout", "stash", "status", "submodule", "switch", "tag", "worktree", "config", "fast-export", "fast-import", "filter-branch", "mergetool", "pack-refs", "prune", "reflog", "remote", "repack", "replace", "annotate", "blame", "bugreport", "count-objects", "difftool", "fsck", "gitweb", "help", "instaweb", "merge-tree", "rerere", "show-branch", "verify-commit", "verify-tag", "whatchanged", "archimport", "cvsexportcommit", "cvsimport", "cvsserver", "imap-send", "p", "quiltimport", "request-pull", "send-email", "svn", "apply", "checkout-index", "commit-graph", "commit-tree", "hash-object", "index-pack", "merge-file", "merge-index", "mktag", "mktree", "multi-pack-index", "pack-objects", "prune-packed", "read-tree", "symbolic-ref", "unpack-objects", "update-index", "update-ref", "write-tree", "cat-file", "cherry", "diff-files", "diff-index", "diff-tree", "for-each-ref", "get-tar-commit-id", "ls-files", "ls-remote", "ls-tree", "merge-base", "name-rev", "pack-redundant", "rev-list", "rev-parse", "show-index", "show-ref", "unpack-file", "var", "verify-pack", "daemon", "fetch-pack", "http-backend", "send-pack", "update-server-info", "check-attr", "check-ignore", "check-mailmap", "check-ref-format", "column", "credential", "credential-cache", "credential-store", "fmt-merge-msg", "interpret-trailers", "mailinfo", "mailsplit", "merge-one-file", "patch-id", "sh-i", "sh-setup"]
@ -77,20 +75,11 @@ func send_command(command):
input.editable = false input.editable = false
completions.hide() completions.hide()
if thread != null:
thread.wait_to_finish()
thread = Thread.new()
thread.start(self, "run_command_in_a_thread", command)
func send_command_async(command): var cmd = repository.shell.run_async(command, false)
input.text = "" yield(cmd, "done")
$TCPServer.send(command+"\n")
func run_command_in_a_thread(command):
var o = repository.shell.run(command, false)
if repository.shell.exit_code == 0: if cmd.exit_code == 0:
$OkSound.pitch_scale = rand_range(0.8, 1.2) $OkSound.pitch_scale = rand_range(0.8, 1.2)
$OkSound.play() $OkSound.play()
else: else:
@ -99,14 +88,14 @@ func run_command_in_a_thread(command):
input.text = "" input.text = ""
input.editable = true input.editable = true
if o.length() <= 1000: if cmd.output.length() <= 1000:
output.text = output.text + "$ " + command + "\n" + o output.text = output.text + "$ " + command + "\n" + cmd.output
else: else:
$Pager/Text.text = o $Pager/Text.text = cmd.output
$Pager.popup() $Pager.popup()
emit_signal("command_done") emit_signal("command_done")
func receive_output(text): func receive_output(text):
output.text += text output.text += text
repository.update_everything() repository.update_everything()