🎓 A1Learner
🔍
0 of 49 lessons completed

Lua Debug Hooks

A debug hook is a function Lua calls at chosen moments while a program runs. You choose the moments with a mask string.

Count function calls

The hook counts each call. Read the count before removing the hook, so the removal call is not counted.

local calls = 0
local function hook(event)
  if event == "call" then
    calls = calls + 1
  end
end
local function a()
  return 1
end
local function b()
  return a() + 1
end
debug.sethook(hook, "c")
local result = b()
local seen = calls
debug.sethook()
print(result)
print(seen)

Count lines run

The hook counts each new line. Two function bodies plus two main lines give four.

local lines = 0
local function hook(event)
  if event == "line" then
    lines = lines + 1
  end
end
local function a()
  return 1
end
local function b()
  return a() + 1
end
debug.sethook(hook, "l")
local result = b()
local seen = lines
debug.sethook()
print(result)
print(seen)

Fire a hook every ten instructions

A count of 10 fires the hook twice during this small loop. The loop total is 15 either way.

local count = 0
debug.sethook(function()
  count = count + 1
end, "", 10)
local total = 0
for i = 1, 5 do
  total = total + i
end
local seen = count
debug.sethook()
print(total)
print(seen)

Example

local function work(n)
  local total = 0
  for i = 1, n do
    total = total + i
  end
  return total
end
local first = 0
debug.sethook(function()
  first = first + 1
end, "", 10)
local small = work(5)
local smallCount = first
debug.sethook()
local second = 0
debug.sethook(function()
  second = second + 1
end, "", 10)
local big = work(10)
local bigCount = second
debug.sethook()
print(small)
print(big)
print(smallCount)
print(bigCount)
print(bigCount > smallCount)

Key points

  • Use debug.sethook to install a hook function.
  • A mask is a string that lists the moments a hook watches.
  • The mask letter c fires the hook on every function call.
  • The mask letter r fires the hook on every function return.
  • The mask letter l fires the hook on every new line.
  • A count fires the hook after that many instructions.

In this example, the same work function runs twice, once with 5 and once with 10. Both runs use the same count of 10, so their hook counts can be compared. The longer run fires the hook more often, and the final print shows that comparison is true.

Note

Counts include the hook machinery itself, so compare only versions with the same shape.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

Which mask letter fires a hook on every function call?