Assertion with coroutines

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Assertion with coroutines

Alexander Gladysh
Hi, all!

I've finally found the cause of that assertion at line 264 of
call_function.cpp. In my case it happens when I calling non-existant
method of luabind-registered class inside my coroutine.

I think that this assertion, as it is now, is quite misleading for
end-user of the library, and that is important since it can be
triggered from inside of Lua code.

The minimal example for reproducing assertion follows.

With best regards,
Alexander.

#include <cassert>
#include <iostream>
#include <sstream>
#include <string>

#include <boost/shared_ptr.hpp>

extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}

#pragma warning(push, 4)
#pragma warning(disable : 4100 4675 4511 4512 4702 4127)

#include "luabind/luabind.hpp"
#include "luabind/object.hpp"

#pragma warning(pop)

namespace luabind
{
  template<class T>
  T * get_pointer(boost::shared_ptr<T> & p)
  {
      return p.get();
  }

  template<class A>
  boost::shared_ptr<const A> * get_const_holder(boost::shared_ptr<A> *
/*unused*/)
  {
      return 0;
  }
}

std::string PopString(lua_State * pState)
{
  const char * pStr = lua_tostring(pState, -1);
  if (pStr != NULL)
  {
    const std::string result(pStr);
    lua_pop(pState, 1);
    return result;
  }
  return std::string();
}

std::string GetErrorMessage(lua_State * pState)
{
  const std::string descr = PopString(pState);
  return (!descr.empty()) ? descr : "(No error message on stack.)";
}

std::string FormatError(lua_State * pState, const std::string & message)
{
  return message + " : " + GetErrorMessage(pState);
}

std::string SafeDoString(lua_State * pState, const std::string & buffer)
{
  try
  {
    if (luaL_loadbuffer(pState, buffer.c_str(), buffer.length(),
buffer.c_str()))
    {
      return FormatError(pState, "Load buffer");
    }

    if (lua_pcall(pState, 0, 0, 0))
    {
      return FormatError(pState, "Pcall");
    }

    return std::string("(No errors)");
  }
  catch (luabind::error & e)
  {
    return FormatError(e.state(), std::string("Luabind: ") + e.what());
  }
}

class Foo
{
public:
  void BindCoroutine(luabind::object obj)
  {
    if (luabind::type(obj) != LUA_TTHREAD)
    {
      lua_pushstring(obj.interpreter(), "Expected coroutine");
      lua_error(obj.interpreter());
    }

    m_Coroutine = obj;

    std::cout << "Registered coroutine " << obj << std::endl;
  }

  void Update()
  {
    m_Coroutine.push(m_Coroutine.interpreter());
    lua_State * pThread = lua_tothread(m_Coroutine.interpreter(), -1);
    assert(pThread);
    lua_pop(m_Coroutine.interpreter(), 1);

    luabind::resume<void>(pThread, "!!!");
  }

private:
  luabind::object m_Coroutine;
};

int main()
{
  lua_State * pState = lua_open();
  if (pState)
  {
    luaopen_base(pState);
    luaopen_string(pState);
    luaopen_table(pState);
    luaopen_math(pState);
    luaopen_debug(pState);
    luaopen_io(pState);
    luabind::open(pState);

    luabind::module(pState)
    [
      luabind::class_< Foo, boost::shared_ptr<Foo> >("Foo_t")
        .def("BindCoroutine", Foo::BindCoroutine)
    ];

    boost::shared_ptr<Foo> pFoo(new Foo());
    luabind::globals(pState)["Foo"] = pFoo;

    std::cout << SafeDoString(
        pState,
        "Foo:BindCoroutine(\n"
        "    coroutine.create(\n"
        "        function()\n"
        "          print(\"before\")\n"
        "          Foo:BadMethod()\n"
        "          print(\"after\")\n"
        "          while true do\n"
        "            local str = coroutine.yield()\n"
        "            print(str)\n"
        "          end\n"
        "        end\n"
        "    )\n"
        ")\n"
      ) << std::endl;

    pFoo->Update();
    pFoo->Update();
    pFoo->Update();

    //  Since it is dependent on pState.
    pFoo.reset();

    lua_close(pState);
    pState = NULL;
  }
  else
  {
    std::cout << "Failed to create Lua state." << std::endl;
  }

  return 0;
}


-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
<a href="http://sel.as-us.falkag.net/sel?cmd=lnk&kid0944&bid$1720&dat1642">http://sel.as-us.falkag.net/sel?cmd=lnk&kid0944&bid$1720&dat1642
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user