How do you define reentrant code?

I’ve found several places around the net where claims are made that Lua is reentrant, but I just found a case (on my platform at least) where Lua is not. I discovered a bug in our system where Lua was being preempted right in the middle of a number to string conversion and the end result was invalid. (Of course, this only occurred about 1 in 200 runs of the code, which made it challenging to figure out what was going on).

The number to string conversion is performed with sprintf(), and sprintf() is not required to be a reentrant function. I’m sure it is on major platforms (Windows/Linux) but unfortunately it is not on ours.

The problem occurred when this sequence of events took place:

* Thread 1: Call Lua, Lua calls sprintf()
* Thread 1 is stopped within sprintf()
* Thread 2 is started
* Thread 2: Call sprintf()
* Thread 2 is stopped after sprintf() completes, Thread 1 resumes

Lua script like this would frequently exhibit the problem:

for i=1,10,1 do
local string = foo .. i
end

The concatenation operation would result in foo + bar instead of foo + i, where “bar” is a fragment of the sprintf() operation left over from Thread 2.

A possible fix for this would be to have Lua use an ftoa() implementation instead of sprintf(). However I fixed it in our case by simply not performing sprintf() in the second thread (this issue was isolated to one portion of our execution fortunately).

If your code is “proven” to be reentrant, but you rely on another library that is not proven, can you still claim your code is reentrant?

Leave a Reply