Can't resize PoolVector if locked

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Andrea

So, i’m looking to do a fairly easy task: i got a 2D path stored in an array (which is filled with Vector2, but it is not a PoolVector2Array), and i want to show it using a Line2D node.
The code is the one below

func show_path():
	$Line2D.clear_points()
	for p in temp_path:
		$Line2D.add_point(p)

I would say 90% of the time it works, but the remaining 10% it throw me this obscure error message, the error points at the line $Line2D.add_point(p)
When it does, the game keep going but the Line2D shows no path: it seems the Line2D.points array remains always of size 1, therefore at the end of the for loop, only the last point of temp_path remains saved

E 0:00:19.045   resize: Can't resize PoolVector if locked.
  <C++ Error>   Condition "alloc->lock.get() > 0" is true. Returned: ERR_LOCKED
  <C++ Source>  ./core/pool_vector.h:528 @ resize()
  <Stack Trace> Unit.gd:160 @ show_path()
                Unit.gd:90 @ request_new_path()
                Map.gd:27 @ close_thread()

I’ve tried searching online but the topic is advanced, it seems it is regarding something about the way the computer allocate memory for the variables.

Additional information:

  • the error appears only on client side (when another instance of the game is already running as server), while the server alone never produces the problem.
    I thought it could have been caused by RPC calls trying to modify the Line2D points at the same time, but eventually i cut down all the RPC and the problem is still there even when show_path() is called directly by the client
  • the game has several Line2D nodes containing the above code: the error happens at every run, if a Line2D is “good” it will always work, when it does not it will never work again (kinda like the Vector2 pool of the line 2D breaks). I noticed there is usually only one “broken” Line2D in a game run
:bust_in_silhouette: Reply From: rossunger

Are you using multithreading by any chance? Is there a mutex lock on the variable you’re trying to change?

A multithread is involved to get the path from an A* algorithm, but i dont think that is the reason, because the multithread makes changes on separate variables, which are read (copied) only after the thread is closed. I managed to make it work without mutex.
See below the rough code

Roughly, the steps are the following

func request_new_path(target):
		A_star_node.get_pathfinding(position, target)   #this call create the secondary thread
		yield(A_star_node, "pathfinding_completed")  #it waits till the thread is closed, when it emit the signal
		if A_star_node.result_distance!=-1:
			temp_path.clear()
			temp_path+=A_star_node.result_path   #it grab the result of the multithread stored in the variable "result_path"
			show_path()   #this is the involved not working function
		else:
			print("Path not found")

Also, if i print the temp_path, I can see it is alway correct.
The problem arise when i try to change the content of the Line2D.points (either with the Line2D.add_point() method, or by manually assigning the array)

Andrea | 2022-02-17 08:06