Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Callback in coroutines not working

in Bugs Posts: 418

Am I doing something silly here that means the callback within the coroutine isn’t being called?
I don’t think it’s a garbage collection issue.

I have a feeling it may be an issue with how the callback is called when the callback is inside a coroutine?

function setup()

    -- Works
    print("Downloading on main thread")
    http.request("https://baconipsum.com/api/?type=meat-and-filler&paras=5&format=text", function(data)
        print("Main thread request done.")
    end)

    -- Does not work
    local co = coroutine.create(function()
        print("Downloading on coroutine thread")
        http.request("https://baconipsum.com/api/?type=meat-and-filler&paras=5&format=text", function(data)
            print("Coroutine request done.")
        end)
    end)
    coroutine.resume(co)

end

Cheers,
Steppers

Tagged:

Comments

  • Posts: 2,690
    @Steppers - is the second end bracket (IE last line in setup function) necessary ?
  • Posts: 418

    @Bri_G Yep, syntactically there’s nothing wrong with it.

  • Posts: 1,350

    I suspect it's because the coroutine is dead, having done its yield. If you did get back in there, you;d get a second unexpected yield, I think.

  • Posts: 298

    Try this:

        -- Does not work
        local co = coroutine.create(function()
            print("Downloading on coroutine thread")
            http.request("https://baconipsum.com/api/?type=meat-and-filler&paras=5&format=text", function(data)
                print("Coroutine request done.")
            end)
        end)
        print(coroutine.status(co))
        coroutine.resume(co)
        print(coroutine.status(co))
    

    You will find, as @RonJeffries said, that co is dead.

  • edited January 20 Posts: 418
    @binaryblues @RonJeffries The Coroutine is dead but I don't think that's the immediate cause.

    This still doesn't work even though the coroutine is just suspended instead.

    ~~~
    function setup()

    -- Works
    print("Downloading on main thread")
    http.request("https://baconipsum.com/api/?type=meat-and-filler&paras=5&format=text", function(data)
    print("Main thread request done.")
    end)

    -- Does not work
    local co = coroutine.create(function()
    print("Downloading on coroutine thread")
    http.request("https://baconipsum.com/api/?type=meat-and-filler&paras=5&format=text", function(data)
    t = data
    end)
    coroutine.yield()
    end)
    print(coroutine.status(co))
    coroutine.resume(co)
    print(coroutine.status(co))
    end

    function draw()
    print(t)
    end
    ~~~

    @Simeon Is there something odd going on in the backend that would cause the callback to never be called at all?
  • edited January 20 Posts: 313

    the coroutine runs, it’s the data that is not return from the http request


    function setup() t = "" local co = coroutine.create(function() print("Downloading on coroutine thread") http.request("https://baconipsum.com/api/?type=meat-and-filler&paras=5&format=text", function(data) print("success") t = data end, function () print("failed") end ) --coroutine.yield() end) print(coroutine.status(co)) coroutine.resume(co) print(coroutine.status(co)) end function draw() print(t) end

    neither success or failed are printed

  • Posts: 418

    @skar Yeah the http callback is never called, the coroutine is fine.

  • edited January 20 Posts: 313

    my guess is once the coroutine runs the reference to the pass or fail functions is deleted, this must happen somewhere in the http.request function because i tested using a global reference function in pass and fail and it still does not work


    -- Use this function to perform your initial setup function setup() t = "" pass = function(data) print("success") t = data end fail = function () print("failed") end local co = coroutine.create(function() print("Downloading on coroutine thread") http.request("https://baconipsum.com/api/?type=meat-and-filler&paras=5&format=text", pass, fail ) --coroutine.yield() end) print(coroutine.status(co)) coroutine.resume(co) print(coroutine.status(co)) --print("Downloading in setup") --http.request("https://baconipsum.com/api/?type=meat-and-filler&paras=5&format=text", pass, fail ) end function draw() print(t) end

    i’m also inclined to believe the issue is with .request because i use coroutine as thread to load my scenes behind a loading screen and have never seen a callback fail

  • Posts: 418

    @skar After a little more digging I believe the issue could potentially stem from native side.

    When the native side calls the callback It’ll be using lua_pcall, passing in the lua_State* but by the look of it, coroutines use a different lua_State object.

    @Simeon this along the right lines? I’m guessing blindly here.

  • edited January 20 Posts: 313

    that’s deeper than my knowledge but what i can say is if you replace http.request with something else that uses callbacks like tween it works as expected

    -- Use this function to perform your initial setup
    function setup()
      t = ""
      pass = function(data)
          print("success")
          t = data
      end
      fail = function ()
        print("failed")
      end
      local co = coroutine.create(function()
        --print("Downloading on coroutine thread")
        --http.request("https://baconipsum.com/api/?type=meat-and-filler&paras=5&format=text", pass, fail )
        --coroutine.yield()
        tween (2, {}, {}, nil, function () print ("tween done") end)
      end)
      print(coroutine.status(co))
      coroutine.resume(co)
      print(coroutine.status(co))
      --print("Downloading in setup")
      --http.request("https://baconipsum.com/api/?type=meat-and-filler&paras=5&format=text", pass, fail )
    end
    
    function draw()
      print(t)
    end
    
    

    you can piggy back into the tween end function and pass data there, it’s a bit of a hack but it works


    -- Use this function to perform your initial setup function setup() t = "" pass = function(data) print("success") t = data end fail = function () print("failed") end local co = coroutine.create(function() print("Downloading on coroutine thread") tween (2, {}, {}, nil, function () http.request("https://baconipsum.com/api/?type=meat-and-filler&paras=5&format=text", pass, fail ) end) coroutine.yield() end) print(coroutine.status(co)) coroutine.resume(co) print(coroutine.status(co)) --print("Downloading in setup") --http.request("https://baconipsum.com/api/?type=meat-and-filler&paras=5&format=text", pass, fail ) end function draw() print(t) end
  • Posts: 418

    @skar Ah, nice find! Other than being a little unwieldy that works quite nicely for what I’m trying to do.
    Cheers :smile:

  • Posts: 418

    @skar You can also see that the callback inside the tween is running on the ‘main’ coroutine too:

    function setup()
    
        -- Works
        print("Downloading on main thread", coroutine.running())
        http.request("https://baconipsum.com/api/?type=meat-and-filler&paras=5&format=text", function(data)
            print("Main thread request done.", coroutine.running())
        end)
    
        -- Does not work
        local co = coroutine.create(function()
            print("Downloading on coroutine thread", coroutine.running())
    
            tween(0.01, {}, {}, nil, function()
                http.request("https://baconipsum.com/api/?type=meat-and-filler&paras=5&format=text", function(data)
                    print("Coroutine request done.", coroutine.running())
                end)
            end).time = 0.0
        end)
        coroutine.resume(co)
    end
    
    function draw()
        print()
    end
    
Sign In or Register to comment.