Notes on Lua/C++ error handling

This is a technical post about how to handle Lua errors in C++ code.

Background

Recently I added support for Lua scripting in Knights. During this process I found out that there are several “gotchas” in terms of how to correctly handle Lua errors in your C++ code. I’m writing this blog post (1) as a way of documenting the issues I found, and (2) because it might be helpful to other programmers who run into similar issues.

I will present this as a series of problems that can occur, and possible solutions to each.

Problem 1: C++ destructors may not called when doing a “longjmp”

The scenario:

Your C++ code calls a Lua API function. Something goes wrong and a Lua error is generated. This causes Lua to do a “longjmp” through your code. Your C++ code contains at least one local variable with a non-trivial destructor.

The problem:

The problem in this scenario is that “longjmp” does not guarantee that destructors will be called. Clearly, this is bad news if you were relying on the destructor to clean up memory or other resources.

Example code:

int MyFunction(lua_State *lua)
{
   std::vector<int> v(10);
   // ...
   lua_call(lua, 0, 0);  // call some lua function
   // ...
   return 0;
}
void Foo(lua_State *lua)
{
   lua_pushcfunction(lua, &MyFunction);
   int result = lua_pcall(lua, 0, 0, 0);
   // ...
}

Discussion:

Imagine that the lua_call above (in MyFunction) results in a Lua error being raised.

At first sight this appears perfectly OK. Lua will handle the error by doing a longjmp. As per the specification of lua_pcall, the stack will be unwound back to the lua_pcall statement in Foo. An error code will be returned into “result”, and execution will continue, with an error message sitting on top of the Lua stack.

The problem is that, on some compilers at least, longjmp() does not call C++ destructors as it unwinds the stack. On such a compiler, the destructor for vector “v” would not be called, and we would have a memory leak.

Indeed, the C++ standard says this:

The function signature longjmp(jmp_buf jbuf, int val) has more restricted behavior in this International Standard. A setjmp/longjmp call pair has undefined behavior if replacing the setjmp and longjmp by catch and throw would invoke any non-trivial destructors for any automatic objects.

(Note: I have seen different wording for this in different places; the above comes from a Stack Overflow answer).

If you think about it, this means that most C++ programs that use longjmp would have undefined behaviour. Considering that Lua uses longjmp ubiquitously for error handling, this is not ideal 🙂

The solution:

The easiest solution is to compile Lua as C++. (In Visual Studio, use option /TP; in GCC, compile the code with g++ instead of gcc.) When Lua is compiled as C++, it uses try/catch instead of setjmp/longjmp for error handling. Problem solved.

Of course, compiling Lua as C++ might not always be practical. For example, we might be working with an external Lua library that has already been compiled as C, or we might want to disable C++ exception handling for performance reasons. In these cases, the only real solution is “don’t do that”; in other words, don’t create stack objects in such a way that destructors would need to be called if there was a Lua error. Of course, this requires some careful programming; if you are going down this route, it would be worth reading this mailing list thread where the issue and some possible solutions are discussed.

What does Knights do?

In Knights I opted to compile Lua as C++. This is the simplest solution, and the overheads of exception handling have not proved to be a problem in practice (remember that Knights is only a simple 2D game with low CPU and RAM requirements in any case).

Problem 2: C++ exceptions should not propagate through Lua

The scenario:

We have written a C++ function and made it available to Lua (via lua_pushcfunction or lua_pushcclosure). Our C++ function can throw exceptions.

The problem:

If Lua calls our C++ function then there is the risk that an exception might be thrown and propagate up through the Lua source code. This is a problem because Lua is written in C, and therefore cannot be assumed to be exception safe in the C++ sense. Although we cannot know for sure that throwing an exception through Lua will be unsafe, we should err on the side of caution and assume that it is unsafe unless proven otherwise.

Example code:

int MyFunction(lua_State *lua)
{
   throw std::runtime_error("Boo!");
}
void Test(lua_State *lua)
{
   lua_pushcfunction(lua, &MyFunction);
   lua_pcall(lua, 0, 0, 0);
}

This code will cause a std::runtime_error to propagate up through the Lua implementation, which is a bad idea for the reasons mentioned above.

The solution:

There is only really one solution, which is to ensure that C++ functions exposed to Lua do not throw exceptions (i.e., they should have the nothrow guarantee).

The simplest way to ensure that is to enclose each function in a try/catch block, e.g.

int MyFunction(lua_State *lua)
{
   // This function is to be exposed to Lua
   try {
      // insert code here
   } catch (std::exception &e) {
      luaL_error(lua, "C++ exception thrown: %s", e.what());
   } catch (...) {
      luaL_error(lua, "C++ exception thrown");
   }
}

This code converts any C++ exception thrown into a Lua error. (If the exception is derived from std::exception, we construct a more useful Lua error message by calling std::exception::what(); otherwise, we just use a generic error message.)

What does Knights do?

One objection to the above is that it would be tedious to write those try/catch clauses in each and every function that we wish to expose to Lua. In Knights, I addressed this by defining a wrapper function “PushCClosure” that is a replacement for lua_pushcclosure. This automates the task of wrapping the enclosed C++ function in a try/catch block. Those interested in the implementation of PushCClosure may wish to refer to its source code.

Problem 3: Avoiding Lua “panics”

The scenario:

C++ calls a Lua API function, and the Lua API function raises a Lua error. Unfortunately, the C++ code did not call Lua in the so-called “protected mode” and therefore, Lua “panics”.

The default action after a panic is for Lua to abort the program. Clearly, this is undesirable in production code.

Example:

The following code illustrates the problem. The code is supposed to read the contents of the global variable “EXAMPLE” and return it as a std::string.

std::string Example_Bad(lua_State *lua)
{
   lua_getglobal(lua, "EXAMPLE");           // push value of EXAMPLE onto the stack
   const char *c = lua_tostring(lua, -1);   // read stack top (as char *)
   std::string result = c ? c : "";         // store to a std::string
   lua_pop(lua, 1);                         // restore the stack
   return result;
}

Discussion:

The problem with the above code is that the calls to either lua_getglobal or lua_tostring might raise an error. For example, a maliciously-minded user might write the following:

local m = {}
function m.__index(tbl, key)
   error("Boo!")
end
setmetatable(_G, m)

Then, the call to lua_getglobal will execute the __index metamethod, which in turn raises an error. The C++ code does not handle the error, and the program aborts.

The solution:

Unfortunately, there is no way to directly check for errors from a Lua API function. Instead, you are supposed to call the Lua API in “protected mode” if you care about error handling. (This often traps beginners, who just write Lua API calls without thinking about what happens when there is an error.)

Calling Lua in “protected mode” is, unfortunately, somewhat tedious. You have to wrap your use of the Lua API inside a lua_pcall, as follows:

std::string Example2_Good(lua_State *lua)
{
   // Create a dummy struct which will be used for the pcall.
   struct Pcall {
      std::string result;  // Will hold the result.

      static int run(lua_State *lua) {
         // Read the pointer to the Pcall struct.
         Pcall *p = static_cast<Pcall*>(lua_touserdata(lua, 1));

         // Get the global "EXAMPLE" and store it in the Pcall struct.
         lua_getglobal(lua, "EXAMPLE");
         const char *c = lua_tostring(lua, -1);
         if (c) p->result = c;

         // Done.
         // (Note there is no need to pop the stack, 
         // Lua will do that for us when we leave the function.)
         return 0;
      }
   };

   Pcall p;
   lua_pushcfunction(lua, &Pcall::run);
   lua_pushlightuserdata(lua, &p);
   int result = lua_pcall(lua, 1, 0, 0);

   if (result != LUA_OK) {
      // Handle error here (e.g., throw C++ exception).
      // Don't forget to pop error message off the Lua stack.
   } 

   // Operation was successful. Return the result.
   return p.result;
}

As you can see, the general idea is to create a local struct, with a static “run” method, and then lua_pcall that method. A pointer to the struct is passed as the sole Lua argument; this allows you to read from and/or write to the struct from within the “run” method.

Importantly, neither lua_pushcfunction nor lua_pushlightuserdata can raise Lua errors, therefore they are safe to call outside of the pcall wrapper.

Note: Panic Functions

An alternative strategy would be to install a panic function, using lua_atpanic. However, it’s not really recommended to use panic functions for regular, everyday error handling. (For one thing, one is never quite sure what is left behind on the Lua stack after a Lua panic.) Instead it is better to use the lua_pcall method as described above.

What does Knights do?

In Knights I don’t currently wrap Lua API calls in a lua_pcall. (The exception is when I call Lua functions, where I do generally use lua_pcall instead of lua_call.) Therefore, if any top-level API calls trigger a Lua error, then a Lua panic occurs.

In Knights I have set up a panic function that throws a C++ exception. When this exception is caught, Knights assumes that the lua_State is unusable and closes it as soon as possible. The server then resets itself and execution continues.

While this method works, it is not particularly pleasant because any clients connected to the server do not receive any explanation of what happened. Their connections are just immediately closed when the Lua panic is handled.

Some time I would like to modify Knights to wrap all uses of the Lua API inside lua_pcall wrappers, as described above. This would ensure clean handling of all Lua errors. (The panic function would be kept, but it would only be there as a “backup” in case I ever forgot to put a lua_pcall wrapper in some place where it was needed.)

Further Reading

The Lua wiki has a page on Lua/C++ error handling:
http://lua-users.org/wiki/ErrorHandlingBetweenLuaAndCplusplus

Here is another blog post on this topic:
http://julipedia.meroh.net/2011/01/error-handling-in-lua.html

Knights Lua module system added

I’ve done quite a bit of work recently on making Knights Lua-scriptable.

  • Knights has been completely converted to use Lua for configuration. The old *.txt files in knights_data are gone.
  • “knights_data” has been split into separate “client” and “server” subdirectories.
  • A Lua module system has been implemented. Basically, a “module” is a self-contained directory that goes into knights_data/server.
  • Knights itself comes with a module called “classic” which implements the classic Knights gameplay that we all know and love.
  • Additional modules can be installed, by copying them into knights_data/server. These will modify the gameplay in various ways.
  • Modules only need to be installed on the server, not on the client machine. If the module contains graphics or sound files then these will be downloaded to the client machine as required.
  • As an example of what modules can do, I have converted ImpassIve_rus’s “multiwand” modification to be a Knights module. Installing this module on a server does two things:
    • The wand graphics are replaced so that each wand is colour coded.
    • Two new “Type of Wand” options are added: “Multiple Wands” (this adds the wand of securing and the wand of destruction at the same time); and “All Wands” (this adds all four wand types to the dungeon at the same time).
  • Users who know Lua programming can write their own modules. A module needs to contain at least one Lua code file, plus it can optionally contain new graphics and sound files.

There is a lot of documentation available on the wiki for those who want to make modules of their own.

Of course, this change is not without its disadvantages; the main one being that mod-making now requires a bit more knowledge, since you have to know Lua programming, whereas before it was just editing a txt file. However, in exchange for that, we get a lot more flexibility — you can do things in Lua code that simply aren’t possible in .txt files. I think the tradeoff is worth it.

If you do want to start Knights Lua programming and you find you don’t understand something, or run into other problems, then feel free to post on the Knights forum and I will try my best to help. I expect there to be a few “teething problems” initially, as the Lua API is new and no doubt has bugs and/or missing features. But with your help (in reporting issues), we can get those things fixed, over time 🙂

Finally, just to be clear, note that the Lua version of Knights isn’t released yet. I aim to do that by the end of August.

Tutorial improvements

For my next trick I intend to add a better tutorial to Knights. Although the current tutorial is OK, it doesn’t really explain things in a very structured way and I think it probably blasts too much information at the player at once. The result is that people get confused, don’t really understand how to play Knights, and as a result, no doubt they think the game is “rubbish” and go do something else. Whereas if they had a better understanding, they would enjoy it a lot more.

For those reasons, I have decided to do some work on the tutorial. I posted some ideas in this forum thread for those who are interested. But anyway, that is what I am going to be working on for the next couple of weeks. After that the plan would be to do a release with the new tutorial and the Lua changes.

Quest Requirements display

I have added a Quest Requirements display to the in-game screen.

Screenshot showing the new Quest Requirements display
Screenshot showing the new Quest Requirements display (click to enlarge)

Originally I wanted to add a tick or cross icon next to each objective, to show whether you have completed that objective yet or not. However, I didn’t get time for that in the end, so I just left it as a static list of objectives, as shown above.

(Also, there is some debate as to whether we should always tell players whether they have completed each quest objective. For example, in a duel to the death, one of the objectives is “secure all entry points”, but players would not normally know whether they have secured the last entry point yet – so should we give this information away by telling them that the objective is complete? Hmm… perhaps it should be an option.)

Anyway, there is now just one more issue to fix (namely: invisible knights should be visible to other players on the same team), then it will be time to do the next release…

About Knights

Knights is a multiplayer dungeon questing game. For more information please visit http://www.knightsgame.org.uk/.

Progress update – making all games team games

Hi everyone, this is just a quick post to report some recent progress I have made on Knights.

It’s true that not much in the way of Knights development has happened recently (well, since January really…) — however, I did get some time to work on Knights yesterday and today and hopefully this should continue into the near future at least.

So I have been busy working on the first stage of the plan I posted last month, which was to remove the separate “team duel to death” quest and instead make ALL games team games. Here’s a screenshot of the new quest menu:

Quest selection screen (click to enlarge)
Quest selection screen (click to enlarge)

As you can see I have added five new house colours, this gives us enough colours for up to 12-player games which should be enough for now (and I can easily add more if needed). I also fixed the bug where entry points secured by the Black player were too dark (so black is now a usable colour for duel to the death quests).

Next up will be to implement a Quest Requirements window on the in-game screen, so that people can know what they are supposed to do without having to press ESC.

Knights development plans

OK so Knights development has been a bit quiet recently, but today I went through Trac and planned out what I would like to do in the next few releases. The plan ended up looking something like this:

  • Version 20 (the next release):
    • Get rid of the separate “Team Duel to the Death” quest type, and instead make all games team games (as proposed in the forum a while back).
    • Add a “Quest Requirements” box on the right hand side of the screen, this will show you a “checklist” of what you have to do (e.g. “Find 4 gems” and “Return to entry point”) plus a little tick or cross next to each item. The idea being to make it a bit clearer exactly what you are supposed to be doing in each quest. (You can already get the quest requirements by pressing ESC, but it is a bit non-obvious, especially to new players.)
  • Version 21: improve “modding” support (see this thread)
    • Make mods easier to install, by simply creating a new directory in “knights_data” (instead of having to edit the existing “knights_data” files as you do at the moment).
    • Change the Knights client so that it downloads all graphics data from the server, instead of looking in the local “knights_data” directory. This means that mods could be installed on the server side only, and players would automatically see the changes without needing to update their Knights installation at all.
    • Tidy up ImpassIve_Rus’s mod for multiple wand types and support it as the first official Knights mod.
  • Version 22
    • I would like to improve the Tutorial. I think a game like Knights needs a strong tutorial, since there is a lot of stuff you can do in the game, and it can be a bit confusing for newbies. The current tutorial is OK but there is definitely room for improvement.
    • Some other minor improvements, e.g. fix some bugs when players get eliminated (which Moo has pointed out recently).

There is also the small matter of the Knights Map Editor which is currently in a somewhat neglected state. I was thinking of rewriting this in C#, as that would give me an excuse to learn C# (and therefore increase my employability) however it doesn’t look like I will be able to do that any time soon. I plan to concentrate on Knights itself for the time being.

Still not sure when I am going to get time to work on the above, but at least there is a plan in place now 🙂

Happy New Year!

Just wanted to say a big Thank You and Happy New Year to all Knights players.

Looking back, I am amazed at how far this little game has come. I first started working on the project back in 2002, although at that point, the plan was not to make an exact remake of Amiga Knights, but instead to make my own game which was “based on” the concepts of the original. However, I wasn’t having much success with that so in about 2004 I decided to change course and just do a remake of the original Knights; I figured I could always add my own new features later if I wanted.

Coding began in earnest in 2005 and the first actual release was right at the end of 2006. About two years after that, the game was complete enough that I decided to announce it on a couple of Amiga forums. At this point it was still fairly basic, with only 2 player support and no central Knights server yet, but it still generated some interest and I was soon getting emails like “why can’t I compile this game on Linux” and “why doesn’t the network support work properly” (LOL). By mid 2009 I had the central server up and running and at the end of 2009 the Multiplayer support (i.e. more than 2 knights in the dungeon) was in place. It was at this point that we discovered that Knights is actually a lot more fun in multiplayer than the original 2 player game, and we even got the original creator (Kalle Marjola) along for a few games 🙂

2010 saw somewhat slower progress — although a couple new features (including a tutorial) were added, along with lots of bug fixing. This year (2011) the most important development was the addition of the “Knights game listing” on the Server List page. With this, I feel that the final piece of the puzzle is now in place: it is now possible to actually meet other players online (something that was surprisingly difficult beforehand) and indeed we are now regularly having 4 or 5 player games every week. (Thanks to K9 for suggesting this feature!)

So, what will the new year bring? With the basic Knights gameplay now in place, and an active (albeit small) community of players, I suppose the next logical step would be to add new gameplay features: new quest types, new room designs, new monsters and items, and so on. At this point I could use some input from players: if you have any new gameplay ideas, please throw them my way 🙂

In the meantime, best wishes to everyone for the new year and may the games continue into 2012 and beyond.

Coming soon: Knights version 019

So this is just a quick update to let you all know what I’ve been working on recently.

Apart from general bug fixing I have so far added two new features to the next version of Knights. These are:

  1. Improvements to team games. I’ve fixed the glitches we found recently and disabled friendly fire for team games. I’ve also added a team chat feature (send chat messages only to your team mates) and allowed more than two teams in a game.
  2. I made a change to the dungeon generator to allow it to reflect and/or rotate the predefined dungeon rooms. This is a “cheap” way of adding a bit more variety into the generated dungeons. It effectively means there are now eight different versions of each room (for the mathematicians, this is the D8 symmetry group…) Here is an example:

A familiar gnome book room... or is it?
A familiar gnome book room... or is it?

In addition I will try to add the following if I get time:

  1. Deathmatch quest type. This has been suggested a couple of times now. Here’s my proposal for how it should work:
    • Knights will spawn at a random entry point (i.e. it’s a different point each time you respawn; knights don’t have a fixed “base” location in this game type).
    • You get one point for a kill, and lose one point for a suicide (e.g. falling down a hole or zombifying yourself).
    • There is a time limit and the player with the highest number of points when the time runs out is the winner.
  2. I also wanted to have a go at implementing Loki’s suggested ogre quest (see previous post). This means importing the ogre graphics into the game, defining how the ogre behaves and designing a room layout for the ogre’s lair.

The plan currently is to release this either later in December, or early January.

Ogre graphics

A gentleman named Loki Trickster has sent me some ogre graphics for use in Knights. I have reproduced some of them below with his permission.

walk

strike

The idea is that the ogre would be a slow-moving, but powerful, “boss” monster. He would have his own room (a bit like the guarded exit or Necronomicon rooms), probably with a lot of corpses in it, and he would attack any vampire bats or zombies that came near him. Perhaps there could be a special quest type to kill the ogre, or bring something back from his room.

Unfortunately I’m not able to add the ogre to the game right now (due to lack of time), but as I’ve said before, I’m planning to add a modding system to Knights, which will make it easy to add new monsters (and other things) to the game. I’m a bit busy at the moment but I should be able to make some progress on that in December.

Reminder: Knights game tomorrow

Also I just want to remind people that we are planning a Knights multiplayer game for tomorrow (13th November) at 7pm GMT. If you want to find out what Knights is all about, then why not log on to the server at that time, and join us for a few quests?

New Knights game listing, and regular Knights game on Sundays

Some of you may have noticed that it is difficult to find an online game of Knights, because there is often nobody online. To help solve this problem, I have set up a listing of pre-arranged games on the Server List page. The idea is that you can check the list, find a time that’s convenient to you, and then log on at that time and play. You can also vote for games (this gives an idea of how many players will show up to each game) and add your own games to the list, which other players will then be able to vote for.

We have also now set up a regular weekly game, taking place at 7pm GMT (2pm EST) on Sundays. Everybody is invited to join — just log on to the server at that time. Last week five players turned up, and we had a great time — Knights really is great fun (and quite hilarious) when there are four or five knights running around at the same time. This week I hope to get even more players, so why not join us this Sunday?

About Knights

Knights is a multiplayer dungeon bashing game. Players must explore randomly generated dungeons and compete to be the first to solve various quests. For more information please visit http://www.knightsgame.org.uk/.

Knights development plans

No doubt regular readers (if there are any left!) will have noticed that Knights development has all but stalled in the last few months. But there is some good news: I have a bit more free time now, and I should be able to spend around 1 day per week on Knights, at least, over the next few weeks.

So what are my plans for Knights?

Well, firstly I want to do a new release of Knights itself, which will fix a number of bugs and will also add a “Random Quest” button to the quest selection screen. This will completely randomize all of the quest settings, and is useful for those times when you just can’t decide what quest to play next.

Secondly, I want to release the source code for the map editor, and write up some documentation for it. (Currently there is a binary only release of the map editor, but there has never been a “proper” release with source code.)

After that, the big new feature is going to be a modding system, so that users can create their own content (dungeon layouts, new monsters, etc) for the game. The aims for the modding system are as follows:

  1. Content will be divided into “modules”. Content creators will create and upload modules. Players will download modules and install them in their Knights directory, where they will be automatically detected and loaded by the game.
  2. Modules will consist of Lua script files, plus (optionally) graphic and sound files.
  3. Modules will (ideally) be able to add any of the following to the game:
    1. New dungeon tiles.
    2. New room layouts. (Either “static” rooms previously designed in the Map Editor, or “dynamic” rooms generated by a Lua script at run time.)
    3. New items. (Either new effects for existing items — e.g. new potion/scroll effects — or completely new item types.)
    4. New monsters (possibly with new AI routines coded in Lua).
    5. New quest objectives.
    6. And so on.
  4. The module system should integrate with the Map Editor, so that (for example) you can create a module containing new tile types, and then load those tiles into the Map Editor for use in your room layouts.
  5. Modules should be able to add to the Quest Selection menu. For example you might want to add new book or wand types, or new dungeon types, or maybe even a whole new setting entirely.
  6. The Lua scripting should be kept as simple as possible, so that it is possible to create simple modules with little or no programming knowledge. (Obviously, more advanced modules might require greater programming knowledge.)

Note the above is mostly a “wish list” at the moment. I’m not promising to do all of the above. (But the nice thing is that it can be worked on incrementally; even if I only get some of the above items done, there will still be a useful product at the end of it.)

As for timings: I hope to do the new Knights release next week. After that, I can’t really say how long before the “module system” is up and running, because it is quite a big project… but I’ll keep you posted on how things are progressing 🙂