How do I get the result of OS.execute without blocking the main thread?

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

I want to get, specifically, the output of OS.execute("ping", ["1.1.1.1", "-n", "1"], true, output) without blocking the main thread.

The solution, I believe, would be something to do with threading, but I am not very familiar with threads and I do not know the proper way to implement a “callback” where the result of the above command would be sent to the main thread to then be processed and the side thread killed.

:bust_in_silhouette: Reply From: Ha-kuro

Quite simple actually ~ the third argument just needs to be false
OS.execute("ping", ["1.1.1.1", "-n", "1"], false, output)

Here’s [the docs][1] :slight_smile:

[1]: OS — Godot Engine (stable) documentation in English(%20String%20path%2C%20PoolStringArray%20arguments%2C%20bool-,blocking%3Dtrue,-%2C%20Array%20output%3D%5B%20%5D%2C%20bool%20read_stderr%3Dfalse%2C

This results in output not being set

ynot01 | 2022-08-07 17:43

Per the docs, the output param will be empty if blocking is false (which makes sense).

Have you tried piping the output of ping into a file and monitoring that file from another script?

Bernard Cloutier | 2022-08-08 12:12

Would have issues from the file being locked/actively written from the other thread

If you read the file while it’s being written to the data could be corrupted

ynot01 | 2022-08-10 21:52

I found this gdnative plugin, seems to solve your problem but I haven’t tested it. https://github.com/odedstr/Godot-std_io

Bernard Cloutier | 2022-08-11 12:16

:bust_in_silhouette: Reply From: ynot01

For those curious, this code snippet is what helped me solve this, from “youwin”

The thread.wait_to_finish() returns the return value of the thread.

extends Node2D

var thread: Thread

func _ready() -> void:
    thread = Thread.new()
    thread.start(self, "_thread")
    
    while thread.is_alive():
        yield(get_tree(), "idle_frame")
    
    print(thread.wait_to_finish())
    thread = null

func _thread() -> String:
    var output := []
    var err: int = OS.execute("CMD.exe", ["/C", "dir"], true, output)
    
    if err != 0:
        printerr("Error occurred: %d" % err)
    
    return PoolStringArray(output).join("\n")