Fix resume after yield error

Fixes error that would sometimes occur when closing the Terminal after
calling write() but before the VisualServer had finished drawing the
current frame.
This commit is contained in:
Leroy Hopson 2022-06-26 21:01:11 +07:00
parent 0ae1d80abb
commit cf613708c4
No known key found for this signature in database
GPG key ID: D2747312A6DB51AA
2 changed files with 19 additions and 5 deletions

View file

@ -33,6 +33,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
closing terminals in the Terminal panel of the editor plugin. closing terminals in the Terminal panel of the editor plugin.
- Fixed leaked instances that would occur when PTY exited but child process was still - Fixed leaked instances that would occur when PTY exited but child process was still
running. running.
- Fixed "Resumed function after yield, but class instance is gone" error that would
sometimes occur when closing a Terminal after calling write() but before VisualServer
had finished drawing the current frame.
## [v2.0.0](https://github.com/lihop/godot-xterm/compare/v1.2.1...v2.0.0) - 2021-07-25 ## [v2.0.0](https://github.com/lihop/godot-xterm/compare/v1.2.1...v2.0.0) - 2021-07-25

View file

@ -61,6 +61,8 @@ var buffer := StreamPeerBuffer.new()
var times = 0 var times = 0
var _buffer := []
func set_update_mode(value): func set_update_mode(value):
update_mode = value update_mode = value
@ -78,12 +80,15 @@ func get_cols() -> int:
func write(data) -> void: func write(data) -> void:
assert(data is String or data is PoolByteArray) assert(data is String or data is PoolByteArray)
# FIXME: This will occasionally cause a "Resumed function after yield, but class instance is gone" error after freeing the Terminal instance. # Will be cleared when _flush() is called after VisualServer emits the "frame_pre_draw" signal.
# However, this yield is necessary to ensure the terminal state machines framebuffer is up to date when we make all the draw_* calls. _buffer.push_back(data)
yield(VisualServer, "frame_pre_draw")
_native_terminal.write(data if data is String else data.get_string_from_utf8())
_native_terminal.update() func _flush():
for data in _buffer:
_native_terminal.write(data if data is String else data.get_string_from_utf8())
_native_terminal.update()
_buffer.clear()
func clear() -> void: func clear() -> void:
@ -128,6 +133,12 @@ func _ready():
_refresh() _refresh()
# Ensure the terminal state machine's framebuffer is up to date before
# we make all the draw_* calls caused by writing. We need to use signals
# here rather than yield otherwise we will sometimes get a "Resumed
# function after yield but class instance is gone" error.
VisualServer.connect("frame_pre_draw", self, "_flush")
func _update_theme(): func _update_theme():
# Themes are not propagated through the Viewport, so in order for theme # Themes are not propagated through the Viewport, so in order for theme