VE Lua Documentation

Press F to search!

traceback

Definition


-- @/lua/common/libs/StackTracePlus/StackTracePlus.lua:435
---
-- Public:
-- Collects a detailed stack trace, dumping locals, resolving function names when they're not available, etc.
-- This function is suitable to be used as an error handler with pcall or xpcall
--
-- @param thread An optional thread whose stack is to be inspected (defaul is the current thread)
-- @param message An optional error string or object.
-- @param level An optional number telling at which level to start the traceback (default is 1)
--
-- Returns a string with the stack trace and a string with the original error.
--
function _M.stacktrace(thread, message, level, level_limit, dump_locals)
  if type(thread) ~= "thread" then
    -- shift parameters left
    thread, message, level, level_limit, dump_locals = nil, thread, message, level, level_limit
  end

  thread = thread or coroutine.running()

  level = level or 1
  if dump_locals == nil then
    dump_locals = true
  end

  local dumper = Dumper.new(thread)

  local original_error

  if type(message) == "table" then
    dumper:add("an error object {\n")
    local first = true
    for k,v in pairs(message) do
      if first then
        dumper:add("  ")
        first = false
      else
        dumper:add(",\n  ")
      end
      dumper:add(safe_tostring(k))
      dumper:add(": ")
      dumper:add(safe_tostring(v))
    end
    dumper:add("\n}")
    original_error = dumper:concat_lines()
  elseif type(message) == "string" then
    dumper:add(message)
    original_error = message
  end

  dumper:add('\n=============== Stack Traceback >> START >>\n')
  --print(error_message)

  local level_to_show = level
  if dumper.dumping_same_thread then level = level + 1 end

  local info = dumper.getinfo(level, "nSlf")
  while info do
    if info.what == "main" then
      if string_sub(info.source, 1, 1) == "@" then
        dumper:add_f("(%d) main chunk of file '%s' at line %d\n", level_to_show, string_sub(info.source, 2), info.currentline)
      else
        dumper:add_f("(%d) main chunk of %s at line %d\n", level_to_show, info.source, info.currentline)
      end
    elseif info.what == "C" then
      --print(info.namewhat, info.name)
      --for k,v in pairs(info) do print(k,v, type(v)) end
      local function_name = m_user_known_functions[info.func] or m_known_functions[info.func] or info.name or tostring(info.func)
      dumper:add_f("(%d) %s C function '%s'\n", level_to_show, info.namewhat, function_name)
      --dumper:add_f("%s%s = C %s\n", prefix, name, (m_known_functions[value] and ("function: " .. m_known_functions[value]) or tostring(value)))
    elseif info.what == "tail" then
      --print("tail")
      --for k,v in pairs(info) do print(k,v, type(v)) end--print(info.namewhat, info.name)
      dumper:add_f("(%d) tail call\n", level_to_show)
      if dump_locals then
        dumper:DumpLocals(level)
      end
    elseif info.what == "Lua" then
      local source = info.source
      local function_name = m_user_known_functions[info.func] or m_known_functions[info.func] or info.name
      if source:sub(2, 7) == "string" then
        source = source:sub(9)
      end
      local was_guessed = false
      if not function_name or function_name == "?" then
        --for k,v in pairs(info) do print(k,v, type(v)) end
        function_name = GuessFunctionName(info)
        was_guessed = true
      end
      -- test if we have a file name
      local function_type = (info.namewhat == "") and "function" or info.namewhat
      if info.source and info.source:sub(1, 1) == "@" then
        dumper:add_f("(%d) Lua %s '%s' at file '%s:%d'%s\n", level_to_show, function_type, function_name, info.source:sub(2), info.currentline, was_guessed and " (best guess)" or "")
      elseif info.source and info.source:sub(1,1) == '#' then
        dumper:add_f("(%d) Lua %s '%s' at template '%s:%d'%s\n", level_to_show, function_type, function_name, info.source:sub(2), info.currentline, was_guessed and " (best guess)" or "")
      else
        dumper:add_f("(%d) Lua %s '%s' at line %d of chunk '%s'\n", level_to_show, function_type, function_name, info.currentline, source)
      end
      if dump_locals then
        dumper:DumpLocals(level)
      end
    else
      dumper:add_f("(%d) unknown frame %s\n", level_to_show, info.what)
    end

    level = level + 1
    level_to_show = level_to_show + 1
    if level_limit ~= nil and level > level_limit then
      break
    end
    info = dumper.getinfo(level, "nSlf")
  end

  dumper:add('--------------- << END <<\n')

  return dumper:concat_lines(), original_error
end

Callers

@/lua/vehicle/main.lua
  log("A", "print", tostring(...))
  -- log('A', "print", debug.traceback()) -- find where print is used
end
@/lua/ge/extensions/util/screenshotCreator.lua
      log('E', '', "workerCoroutine: "..value)
      log("E", '', debug.traceback(workerCoroutine))
    end
@/lua/vehicle/extensions/dynamicVehicleData.lua
    if not errorfree then
      log("E", logTag, debug.traceback(workerCoroutine, "workerCoroutine: " .. value))
    end
@/lua/common/libs/timerwheel/timerwheel.lua
local default_err_handler = function(err)
  io.stderr:write(debug.traceback("TimerWheel callback failed with: " .. tostring(err)))
end
@/lua/vehicle/extensions/core/quickAccess.lua
M.registerMenu = function()
  log("E", "quickAccess", "registerMenu is deprecated. Please use core_quickAccess.addEntry: " .. debug.traceback())
end
@/lua/common/utils.lua
  -- to find out who is calling this, you can use this snippet:
  --log('A', "lua.utils.dump-calledby", debug.traceback())
      rawset(_G, key, val)
      log('W', 'globals', debug.traceback('set new global variable: "' .. tostring(key) .. '"  to "'  .. tostring(val) .. '"', 2, 1, false))
    end,
@/lua/ge/main.lua
  log("A", "print", tostring(...))
  -- log('A', "print", debug.traceback()) -- find where print is used
end
@/lua/common/luaBinding.lua
    if not mt then
      --log('E', '', string.format("property '%s.%s' is not found or not writable: %s", getmetatable(t).___type, k, debug.traceback()))
      return
    if not mt then
      --log('E', '', string.format("property '%s.%s' is not found or not writable: %s", getmetatable(t).___type, k, debug.traceback()))
      return
@/lua/vehicle/extensions/escMeasurement.lua
    if not errorfree then
      log("E", logTag, debug.traceback(workerCoroutine, "workerCoroutine: " .. value))
    end
@/lua/ge/extensions/core/quickAccess.lua
M.addEntry = addEntry
M.registerMenu = function() log('E', 'quickAccess', 'registerMenu is deprecated. Please use quickAccess.addEntry: ' .. debug.traceback()) end
@/lua/common/libs/StackTracePlus/StackTracePlus.lua
-- @param message An optional error string or object.
-- @param level An optional number telling at which level to start the traceback (default is 1)
--
@/lua/ge/extensions/core/jobsystem.lua
    if runningFct[fct] then
      --log('D', 'jobsystem', 'job already running. ' .. debug.traceback())
      return
    if not errorfree then
      log('E', 'jobsystem', "job error: " .. tostring(value) .. ' / ' .. debug.traceback(co.t))
    end
@/lua/vehicle/energyStorage.lua
    log("D", "energyStorage.getStorageSafe", string.format("Didn't find storage '%s', returning nilStorage.", name))
    --log("D", "energyStorage.getStorageSafe", debug.traceback())
    --return our nilStorage that accepts all indexes and can be called without errors
@/lua/vehicle/partCondition.lua
        log("E", "partCondition.getConditions", err)
        log("E", "partCondition.getConditions", debug.traceback())
      end
@/lua/vehicle/bullettime.lua
  guihooks.trigger("toastrMsg", {type="error", title="Deprecated API: bullettime", msg="At least one mod is obsolete and needs to be updated by its author. Check the logs for more information"})
  log("E","", "An obsolete mod is using a deprecated API. See traceback below for more information:\n"..debug.traceback())
end
@/lua/vehicle/controller/drivingDynamics/CMU.lua
    -- dump(currentDefaultControlParam)
    -- print(debug.traceback())
    return false
@/lua/ge/map.lua
  if not be then return end
  --log('A', "map.loadMap-calledby", debug.traceback())
  --local timer = hptimer()
@/lua/vehicle/controller.lua
  log("D", "controller.getControllerSafe", string.format("Didn't find controller '%s', returning nilController.", name))
  --log("D", "controller.getControllerSafe", debug.traceback())
  --return our nilController that accepts all indexes and can be called without errors
    log("E", "controller.loadControllerExternal", errorStr)
    log("E", "controller.loadControllerExternal", debug.traceback())
  end
      log("E", "controller.init", errorStr)
      log("E", "controller.init", debug.traceback())
    end