Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ResourceInteractiveLoader in Thread produces 100 lines of error log spam #63493

Open
michael-nischt opened this issue Jul 26, 2022 · 4 comments

Comments

@michael-nischt
Copy link

Godot version

v3.4.4.stable.official [419e713]

System information

Arch Linux 5.18.13, nVidia 3080 Mobile, OpenGL ES 3.2 NVIDIA 515.57

Issue description

ResourceInteractiveLoader.poll() produces error logs when called in a Thread.

ril-errors
(symptomatic error)

Everything looks to be loaded just fine though. It looks very much like a bug to me unless there's something wrong with the following utility. However, if that's the case please let me know what / how to fix it.

extends Reference
class_name ResourceAsyncLoader

# main thread only
var _path : String
var _resource : Resource = null
var _progress : float = 0.0
var _thread : Thread = Thread.new()
# shared
var _mutex : Mutex = Mutex.new()
var _shared_result : int = OK
var _shared_progress : float = 0.0


func _init(path : String) -> void:
	assert(path != null) # and ResourceLoader.exits(path))
	self._path = path
	

func get_progress() -> float:
	return self._progress


func get_resource() -> Resource:
	return self._resource


func poll() -> int:
	var result : int

	if self._resource != null:
		result = ERR_FILE_EOF
	elif not self._thread.is_active():
		#print("START THREAD")
		result = self._thread.start(self, "_thread_run", ResourceLoader.load_interactive(self._path))
	else:
		self._lock("poll")
		result = _shared_result
		self._progress = self._shared_progress
		self._unlock("poll")

	#print("Progress: %s" % [self._progress])

	if result != OK and self._thread.is_active():
		self._progress = 1.0
		self._resource = self._thread.wait_to_finish()
	
	return result


func _thread_run(loader : ResourceInteractiveLoader) -> Resource:
	#print("THREAD STARTED")
	var run : bool = true
	while run:
		var result : int = loader.poll()
		var progress : float = (1.0 + loader.get_stage()) / float(loader.get_stage_count())
		self._lock("_thread_run")
		self._shared_result = result
		self._shared_progress = progress
		#print("Stage: %s / %s" % [loader.get_stage(), loader.get_stage_count()])
		self._unlock("_thread_run")
		if result != OK:
			#print("THREAD is FINISHED!!!")
			return loader.get_resource()
	return null
	

func _lock(_caller : String) -> void:
	#print("LOCK: " + _caller)
	self._mutex.lock()


func _unlock(_caller : String) -> void:
	self._mutex.unlock()
	#print("UNLOCK: " + _caller)

Steps to reproduce

Easiest is with the attached, minimal project:

  1. Open the project
  2. Press Play / F5
  3. Observe Errors Tab inside the Debugger Panel

But my guess is any call to ResourceInteractiveLoader.poll() on a GDscript Thread in a loop causes this?

Minimal reproduction project

ril-async-bug.zip

@Calinou
Copy link
Member

Calinou commented Jul 26, 2022

Related to #41360 and #53374 (where the same error message is printed).

@michael-nischt
Copy link
Author

UPDATE:

I noticed it also happens with ResourceLoader.load(path) in a thread. Meaning it is not specific to the ResourceInteractiveLoader.poll(). Rather setting up the nodes.

func _thread_full(path : String) -> Resource:
	#print("THREAD STARTED")
	var resource : Resource = ResourceLoader.load(path)
	self._lock("_thread_full")
	self._shared_result = ERR_FILE_EOF
	self._shared_progress = 1.0
	self._unlock("_thread_full")
	return resource

@TokisanGames
Copy link
Contributor

We're using ResourceInteractiveLoader not in a thread, without RID issues. Like us, you also aren't loading in a thread. The only thing you're doing is polling in a thread. It's unnecessary. You don't need a thread. Just stick your poller in _process() and dispense with 80% of that complexity.

Threading has historically been part of the experimental side of Godot, so YMMV.

RIDs are one of the hardest things in Godot to debug, which you can read about in #53374. I recommend forgetting about threading in this class.

@michael-nischt
Copy link
Author

Well, we are using it without a dedicated thread for now since the log spam hides all other errors.

That said, poll doesn't seem to be at all. Actually, the reason why we added the threaded version was due to huge frame spikes on an older notebook.

BHSDuncan added a commit to godot-escoria/escoria-demo-game that referenced this issue Apr 21, 2023
…e thread to avoid odd resource/RID loading issues, as noted here: godotengine/godot#63493
StraToN pushed a commit to godot-escoria/escoria-demo-game that referenced this issue Apr 22, 2023
…e thread to avoid odd resource/RID loading issues, as noted here: godotengine/godot#63493
BHSDuncan added a commit to godot-escoria/escoria-game-template that referenced this issue May 4, 2023
…e thread to avoid odd resource/RID loading issues, as noted here: godotengine/godot#63493
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants