0 votes

This is part of a previous question I had asked and not sure if this is an engine issue or something I am doing wrong. However, I find that if I am using the HTTPClient to query a server and the process is interrupted then the game silently crashes with no errors.

To clarify, in my example, a user clicks on Leaderboards, which polls a server and gets data then displays it. However, if the user click the back button before the server's response comes then the game crashes with no errors.

Perhaps there is something wrong with my method? Perhaps the engine?

in Engine by (25 points)

It's hard to tell what the problem is without any code but I use the HTTPClient a lot without any crashes. I think there is something wrong with your method, maybe you free something on back button and the response is trying to use the object you just removed with your back button.

Thanks for the reply. I will post the code in question when I get back to my laptop. However, for now I just have it disable the buttons until the process is done. That seems to work.

Okay, finally got my laptop cord back and powered up! I will share the code for the version checking, where I first noticed it crash out if the player interrupts it.

# Set up some variables
var thread = Thread.new()

func _ready():
    thread.start(self, "versionChecking", "Loading...")

func versionChecking(message):
    get_node("Loading Message").set_text(message)
    # Pull the game version
    var RESPONSE = http.getGameVersion()
    call_deferred(gameUpToDate())
    return RESPONSE

func gameUpToDate():
    var RESPONSE = thread.wait_to_finish()
    # Loading server data is done so end the loading screen
    get_node("/root/global").goto_scene("res://src/splash.scn")

The HTTP script that this calls is set as a global script (singleton) to be called whenever needed. This is the code that this is calling:

# Get game's official version
func getGameVersion():
    talkToServer("version-check.php", "check", "")

# Loads the page and gets the response
func talkToServer(url, mode, data):
    # Connect to host/port
    HTTP = HTTPClient.new()
    RESPONSE = HTTP.connect("whatever.com",80)
    # Wait until resolved and connected
    while(HTTP.get_status() == HTTPClient.STATUS_CONNECTING or HTTP.get_status() == HTTPClient.STATUS_RESOLVING):
        HTTP.poll()
        OS.delay_msec(300)
    # Error catch: Could not connect
    assert(HTTP.get_status() == HTTPClient.STATUS_CONNECTED)
    # Check for a GET or POST command
    if data == "":
        HEADERS =["User-Agent: Pirulo/1.0 (Godot)", "Accept: */*"]
        RESPONSE = HTTP.request(HTTPClient.METHOD_GET, url, HEADERS)
    else:
        QUERY = HTTP.query_string_from_dict(data)
        HEADERS = ["User-Agent: Pirulo/1.0 (Godot)", "Content-Type: application/x-www-form-urlencoded", "Content-Length: " + str(QUERY.length())]
        RESPONSE = HTTP.request(HTTPClient.METHOD_POST, url, HEADERS, QUERY)
    # Make sure all is OK
    assert(RESPONSE == OK)
    # Keep polling until the request is going on
    while (HTTP.get_status() == HTTPClient.STATUS_REQUESTING):
        HTTP.poll()
        OS.delay_msec(300)
    # Make sure request finished
    assert(HTTP.get_status() == HTTPClient.STATUS_BODY or HTTP.get_status() == HTTPClient.STATUS_CONNECTED)
    # Set up some variables
    var RB = RawArray()
    var CHUNK = 0
    var RESULT = 0
    # Raw data array
    if HTTP.has_response():
        # Get response headers
        var headers = HTTP.get_response_headers_as_dictionary()
        while(HTTP.get_status() == HTTPClient.STATUS_BODY):
            HTTP.poll()
            CHUNK = HTTP.read_response_body_chunk()
            if(CHUNK.size() == 0):
                OS.delay_usec(100)
            else:
                RB = RB + CHUNK
        HTTP.close()
        RESULT = RB.get_string_from_ascii()
        # Do something with the response
        if mode == 'check':
            global.GAME_VERSION = RESULT

At the end of the code, it passes the version number to the global variable to be displayed on the menu screen. If this process is interrupted, it silently crashes the game with no error at all. No idea why.

As you can see here, I basically prevent any user input from disrupting this and make it change scenes once the process is done. The same applies to the stats and leaderboard screens.

In Python, I essentially used the same system but did not have to prevent user interaction until it was finished. It would just poll the server and display the information when it was fetched, provided the user didn't change scenes by then.

1 Answer

0 votes

I can't see any problem right now, have you checked the output in the terminal/CMD that is showing sometimes more than the default output in godot.

I also noticed that threads somethimes hide errors so maybe you try to run the http request in "_process(delta)"

by (175 points)

In the Linux version of Godot it does not open a terminal like it does in Windows, though I never actually checked what happens in Windows.

I will try both a Windows test and checking for hidden errors with _process(delta), cheers!

On linux you can start godot in a terminal it will show the same output like Windows
1. Open Terminal in godot folder
2. run ./bin/godot.x11.tools.64 or ./godot.x11.tools.64

I have a shortcut that runs it, I'll just have it run that in Terminal. Thanks again!

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.