Exemplo n.º 1
0
static char* test_api_assertion()
{
  lsb_lua_sandbox *sb = lsb_create(NULL, "lua/counter.lua", "", NULL);
  lsb_err_value ret = lsb_init(sb, NULL);
  mu_assert(!ret, "lsb_init() received: %s", ret);

  lsb_stop_sandbox(NULL);
  mu_assert(lsb_destroy(NULL) == NULL, "not null");
  mu_assert(lsb_usage(NULL, 0, 0) == 0, "not 0");
  mu_assert(lsb_usage(sb, LSB_UT_MAX, 0) == 0, "not 0");
  mu_assert(lsb_usage(sb, 0, LSB_US_MAX) == 0, "not 0");
  mu_assert(strcmp(lsb_get_error(NULL), "") == 0, "not empty");
  lsb_set_error(NULL, "foo");
  mu_assert(lsb_get_lua(NULL) == NULL, "not null");
  mu_assert(lsb_get_lua_file(NULL) == NULL, "not null");
  mu_assert(lsb_get_parent(NULL) == NULL, "not null");
  mu_assert(lsb_get_logger(NULL) == NULL, "not null");
  mu_assert(lsb_get_state(NULL) == LSB_UNKNOWN, "not unknown");
  lsb_add_function(NULL, lsb_test_write_output, "foo");
  lsb_add_function(sb, NULL, "foo");
  lsb_add_function(sb, lsb_test_write_output, NULL);
  mu_assert(lsb_pcall_setup(NULL, "foo") == LSB_ERR_UTIL_NULL, "not null");
  mu_assert(lsb_pcall_setup(sb, NULL) == LSB_ERR_UTIL_NULL, "not null");
  lsb_add_function(NULL, NULL, NULL);
  lsb_pcall_teardown(NULL);
  lsb_terminate(NULL, NULL);
  lsb_terminate(sb, NULL);
  lsb_add_function(sb, lsb_test_write_output, "write_output");

  e = lsb_destroy(sb);
  mu_assert(!e, "lsb_destroy() received: %s", e);
  return NULL;
}
Exemplo n.º 2
0
static char* test_usage_error()
{
  size_t u = lsb_usage(NULL, LSB_UT_MEMORY, LSB_US_CURRENT);
  mu_assert(u == 0, "NULL sandbox memory usage received: %" PRIuSIZE, u);

  lsb_lua_sandbox *sb = lsb_create(NULL, "lua/simple.lua", test_cfg, NULL);
  mu_assert(sb, "lsb_create() received: NULL");

  u = lsb_usage(NULL, LSB_UT_MAX + 1, LSB_US_CURRENT);
  mu_assert(u == 0, "Invalid usage type received: %" PRIuSIZE, u);

  u = lsb_usage(NULL, LSB_UT_MEMORY, LSB_US_MAX + 1);
  mu_assert(u == 0, "Invalid usage stat received: %" PRIuSIZE, u);

  mu_assert(sb, "lsb_create() received: NULL");
  lsb_terminate(sb, "forced termination");
  lsb_state s = lsb_get_state(sb);
  mu_assert(s == LSB_TERMINATED, "lsb_get_state() received: %d", s);
  u = lsb_usage(sb, LSB_UT_MEMORY, LSB_US_CURRENT);
  mu_assert(u > 0, "Terminated memory usage received: 0");

  e = lsb_destroy(sb);
  mu_assert(!e, "lsb_destroy() received: %s", e);

  return NULL;
}
Exemplo n.º 3
0
int lsb_heka_pm_input(lsb_heka_sandbox *hsb,
                      double cp_numeric,
                      const char *cp_string,
                      bool profile)
{
  if (!hsb || hsb->type != 'i') {
    return 1;
  }

  lsb_err_value ret = lsb_pcall_setup(hsb->lsb, pm_func_name);
  if (ret) {
    if (ret != LSB_ERR_TERMINATED) {
      char err[LSB_ERROR_SIZE];
      snprintf(err, LSB_ERROR_SIZE, "%s() function was not found",
               pm_func_name);
      lsb_terminate(hsb->lsb, err);
    }
    return 1;
  }

  lua_State *lua = lsb_get_lua(hsb->lsb);
  if (!lua) return 1;

  if (!isnan(cp_numeric)) {
    lua_pushnumber(lua, cp_numeric);
  } else if (cp_string) {
    lua_pushstring(lua, cp_string);
  } else {
    lua_pushnil(lua);
  }
  return process_message(hsb, NULL, lua, 1, profile);
}
Exemplo n.º 4
0
static char* test_usage_error()
{
  unsigned u = lsb_usage(NULL, LSB_UT_MEMORY, LSB_US_CURRENT);
  mu_assert(u == 0, "NULL sandbox memory usage received: %u", u);

  lua_sandbox* sb = lsb_create(NULL, "lua/simple.lua", 65765, 1000,
                               1024);
  mu_assert(sb, "lsb_create() received: NULL");

  u = lsb_usage(NULL, LSB_UT_MAX + 1, LSB_US_CURRENT);
  mu_assert(u == 0, "Invalid usage type received: %u", u);

  u = lsb_usage(NULL, LSB_UT_MEMORY, LSB_US_MAX + 1);
  mu_assert(u == 0, "Invalid usage stat received: %u", u);

  mu_assert(sb, "lsb_create() received: NULL");
  lsb_terminate(sb, "forced termination");
  u = lsb_usage(sb, LSB_UT_MEMORY, LSB_US_CURRENT);
  mu_assert(u == 0, "Terminated memory usage received: %u", u);

  e = lsb_destroy(sb, NULL);
  mu_assert(!e, "lsb_destroy() received: %s", e);

  return NULL;
}
Exemplo n.º 5
0
int report(lua_sandbox* lsb, double tc)
{
  static const char* func_name = "report";
  lua_State* lua = lsb_get_lua(lsb);
  if (!lua) return 1;

  if (lsb_pcall_setup(lsb, func_name)) return 1;

  lua_pushnumber(lua, tc);
  if (lua_pcall(lua, 1, 0, 0) != 0) {
    char err[LSB_ERROR_SIZE];
    int len = snprintf(err, LSB_ERROR_SIZE, "%s() %s", func_name,
                       lua_tostring(lua, -1));
    if (len >= LSB_ERROR_SIZE || len < 0) {
      err[LSB_ERROR_SIZE - 1] = 0;
    }
    lsb_terminate(lsb, err);
    return 1;
  }

  lsb_pcall_teardown(lsb);
  lua_gc(lua, LUA_GCCOLLECT, 0);

  return 0;
}
Exemplo n.º 6
0
int lsb_heka_timer_event(lsb_heka_sandbox *hsb, time_t t, bool shutdown)
{
  static const char *func_name = "timer_event";

  if (!hsb || (hsb->type != 'o' && hsb->type != 'a')) {
    return 1;
  }

  lua_State *lua = lsb_get_lua(hsb->lsb);
  if (!lua) return 1;

  if (lsb_pcall_setup(hsb->lsb, func_name)) {
    char err[LSB_ERROR_SIZE];
    snprintf(err, LSB_ERROR_SIZE, "%s() function was not found", func_name);
    lsb_terminate(hsb->lsb, err);
    return 1;
  }
  // todo change if we need more than 1 sec resolution
  lua_pushnumber(lua, t * 1e9);
  lua_pushboolean(lua, shutdown);

  unsigned long long start, end;
  start = lsb_get_time();
  if (lua_pcall(lua, 2, 0, 0) != 0) {
    char err[LSB_ERROR_SIZE];
    size_t len = snprintf(err, LSB_ERROR_SIZE, "%s() %s", func_name,
                          lua_tostring(lua, -1));
    if (len >= LSB_ERROR_SIZE) {
      err[LSB_ERROR_SIZE - 1] = 0;
    }
    lsb_terminate(hsb->lsb, err);
    return 1;
  }
  end = lsb_get_time();
  lsb_update_running_stats(&hsb->stats.te, (double)(end - start));
  lsb_pcall_teardown(hsb->lsb);
  lua_gc(lua, LUA_GCCOLLECT, 0);
  return 0;
}
Exemplo n.º 7
0
int process(lua_sandbox* lsb, double ts)
{
  static const char* func_name = "process";
  lua_State* lua = lsb_get_lua(lsb);
  if (!lua) return 1;

  if (lsb_pcall_setup(lsb, func_name)) return 1;

  lua_pushnumber(lua, ts);
  if (lua_pcall(lua, 1, 1, 0) != 0) {
    char err[LSB_ERROR_SIZE];
    int len = snprintf(err, LSB_ERROR_SIZE, "%s() %s", func_name,
                       lua_tostring(lua, -1));
    if (len >= LSB_ERROR_SIZE || len < 0) {
      err[LSB_ERROR_SIZE - 1] = 0;
    }
    lsb_terminate(lsb, err);
    return 1;
  }

  if (!lua_isnumber(lua, 1)) {
    char err[LSB_ERROR_SIZE];
    int len = snprintf(err, LSB_ERROR_SIZE,
                       "%s() must return a single numeric value", func_name);
    if (len >= LSB_ERROR_SIZE || len < 0) {
      err[LSB_ERROR_SIZE - 1] = 0;
    }
    lsb_terminate(lsb, err);
    return 1;
  }

  int status = (int)lua_tointeger(lua, 1);
  lua_pop(lua, 1);

  lsb_pcall_teardown(lsb);

  return status;
}
Exemplo n.º 8
0
int lsb_heka_pm_analysis(lsb_heka_sandbox *hsb,
                         lsb_heka_message *msg,
                         bool profile)
{
  if (!hsb || !msg || hsb->type != 'a') return 1;

  if (lsb_pcall_setup(hsb->lsb, pm_func_name)) {
    char err[LSB_ERROR_SIZE];
    snprintf(err, LSB_ERROR_SIZE, "%s() function was not found", pm_func_name);
    lsb_terminate(hsb->lsb, err);
    return 1;
  }

  lua_State *lua = lsb_get_lua(hsb->lsb);
  if (!lua) return 1;
  return process_message(hsb, msg, lua, 0, profile);
}
lsb_err_value restore_global_data(lsb_lua_sandbox *lsb)
{
  if (!lsb) {
    return LSB_ERR_UTIL_NULL;
  }
  if (!lsb->state_file || !file_exists(lsb->state_file)) {
    return NULL;
  }

  // Clear the sandbox limits during restoration.
#ifdef LUA_JIT
  lua_gc(lsb->lua, LUA_GCSETMEMLIMIT, 0);
#else
  size_t limit = lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT];
  lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT] = 0;
#endif
  lua_sethook(lsb->lua, NULL, 0, 0);

  int err = luaL_dofile(lsb->lua, lsb->state_file);
  if (err) {
    if (LUA_ERRFILE != err) {
      int len = snprintf(lsb->error_message, LSB_ERROR_SIZE,
                         "restore_global_data %s",
                         lua_tostring(lsb->lua, -1));
      if (len >= LSB_ERROR_SIZE || len < 0) {
        lsb->error_message[LSB_ERROR_SIZE - 1] = 0;
      }
      lsb_terminate(lsb, NULL);
      return LSB_ERR_LUA;
    }
  }
#ifdef LUA_JIT
  lua_gc(lsb->lua, LUA_GCSETMEMLIMIT,
         lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT]); // reinstate limit
#else
  lua_gc(lsb->lua, LUA_GCCOLLECT, 0);
  lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT] = limit;
  lsb->usage[LSB_UT_MEMORY][LSB_US_MAXIMUM] =
      lsb->usage[LSB_UT_MEMORY][LSB_US_CURRENT];
#endif
  return NULL;
}
Exemplo n.º 10
0
char* lsb_destroy(lsb_lua_sandbox *lsb)
{
  char *err = NULL;
  if (!lsb) {
    return err;
  }

  if (preserve_global_data(lsb)) {
    size_t len = strlen(lsb->error_message);
    err = malloc(len + 1);
    if (err != NULL) {
      strcpy(err, lsb->error_message);
    }
  }
  lsb_terminate(lsb, NULL);
  lsb_free_output_buffer(&lsb->output);
  free(lsb->state_file);
  free(lsb->lua_file);
  free(lsb);
  return err;
}
Exemplo n.º 11
0
int lsb_heka_pm_output(lsb_heka_sandbox *hsb,
                       lsb_heka_message *msg,
                       void *sequence_id,
                       bool profile)
{
  if (!hsb || !msg || hsb->type != 'o') return 1;

  if (lsb_pcall_setup(hsb->lsb, pm_func_name)) {
    char err[LSB_ERROR_SIZE];
    snprintf(err, LSB_ERROR_SIZE, "%s() function was not found", pm_func_name);
    lsb_terminate(hsb->lsb, err);
    return 1;
  }

  lua_State *lua = lsb_get_lua(hsb->lsb);
  if (!lua) return 1;

  int nargs = 0;
  if (sequence_id) {
    nargs = 1;
    lua_pushlightuserdata(lua, sequence_id);
  }
  return process_message(hsb, msg, lua, nargs, profile);
}
Exemplo n.º 12
0
void lsb_heka_terminate_sandbox(lsb_heka_sandbox *hsb, const char *err)
{
  lsb_terminate(hsb->lsb, err);
}
Exemplo n.º 13
0
static int process_message(lsb_heka_sandbox *hsb, lsb_heka_message *msg,
                           lua_State *lua, int nargs, bool profile)
{
  unsigned long long start, end;

  hsb->msg = msg;
  if (profile) {
    start = lsb_get_time();
  }
  if (lua_pcall(lua, nargs, 2, 0) != 0) {
    char err[LSB_ERROR_SIZE];
    const char *em = lua_tostring(lua, -1);
    if (hsb->type == 'i' && strcmp(em, LSB_SHUTTING_DOWN) == 0) {
      return 0;
    }
    size_t len = snprintf(err, LSB_ERROR_SIZE, "%s() %s", pm_func_name, em);
    if (len >= LSB_ERROR_SIZE) {
      err[LSB_ERROR_SIZE - 1] = 0;
    }
    lsb_terminate(hsb->lsb, err);
    return 1;
  }
  if (profile) {
    end = lsb_get_time();
    lsb_update_running_stats(&hsb->stats.pm, (double)(end - start));
  }
  hsb->msg = NULL;

  if (lua_type(lua, 1) != LUA_TNUMBER) {
    char err[LSB_ERROR_SIZE];
    size_t len = snprintf(err, LSB_ERROR_SIZE,
                          "%s() must return a numeric status code",
                          pm_func_name);
    if (len >= LSB_ERROR_SIZE) {
      err[LSB_ERROR_SIZE - 1] = 0;
    }
    lsb_terminate(hsb->lsb, err);
    return 1;
  }

  int status = (int)lua_tointeger(lua, 1);
  switch (lua_type(lua, 2)) {
  case LUA_TNIL:
    lsb_set_error(hsb->lsb, NULL);
    break;
  case LUA_TSTRING:
    lsb_set_error(hsb->lsb, lua_tostring(lua, 2));
    break;
  default:
    {
      char err[LSB_ERROR_SIZE];
      int len = snprintf(err, LSB_ERROR_SIZE,
                         "%s() must return a nil or string error message",
                         pm_func_name);
      if (len >= LSB_ERROR_SIZE || len < 0) {
        err[LSB_ERROR_SIZE - 1] = 0;
      }
      lsb_terminate(hsb->lsb, err);
      return 1;
    }
    break;
  }
  lua_pop(lua, 2);
  lsb_pcall_teardown(hsb->lsb);

  if (status > 0) {
    char err[LSB_ERROR_SIZE];
    size_t len = snprintf(err, LSB_ERROR_SIZE,
                          "%s() received a termination status code",
                          pm_func_name);
    if (len >= LSB_ERROR_SIZE) {
      err[LSB_ERROR_SIZE - 1] = 0;
    }
    lsb_terminate(hsb->lsb, err);
    return 1;
  } else if (status == LSB_HEKA_PM_FAIL) {
    ++hsb->stats.pm_cnt;
    ++hsb->stats.pm_failures;
  } else  if (hsb->type != 'o' || status != LSB_HEKA_PM_RETRY) {
    ++hsb->stats.pm_cnt;
  }
  return status;
}
Exemplo n.º 14
0
static int output_message(hs_output_plugin* p)
{
  int ret = 0, te_ret = 0;
  bool sample = p->sample;
  time_t current_t = time(NULL);
  p->matched = false;

  struct timespec ts, ts1;
  double delta = 0;
  size_t sequence_id = 0;

  if (p->msg->msg) { // non idle/empty message
    double mmdelta = 0;
    if (sample) clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
    p->matched = hs_eval_message_matcher(p->sb->mm, p->msg);
    if (sample) {
      clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts1);
      mmdelta = hs_timespec_delta(&ts, &ts1);
    }
    if (p->matched) {
      if (p->async_len) {
        sequence_id = p->sb->stats.pm_cnt + 1;
        int i = sequence_id % p->async_len;
        p->async_cp[i].input.id = p->cur.input.id;
        p->async_cp[i].input.offset = p->cur.input.offset;
        p->async_cp[i].analysis.id = p->cur.analysis.id;
        p->async_cp[i].analysis.offset = p->cur.analysis.offset;
      }
      ret = hs_process_message(p->sb->lsb, (void*)(sequence_id));
      if (sample) {
        clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
        delta = hs_timespec_delta(&ts1, &ts);
      }
      if (ret <= 0) {
        pthread_mutex_lock(&p->cp_lock);
        switch (ret) {
        case 0: // sent
          ++p->sb->stats.pm_cnt;
          p->batching = false;
          break;
        case -1: // failure
          ++p->sb->stats.pm_cnt;
          ++p->sb->stats.pm_failures;
          break;
        case -2: // skip
          ++p->sb->stats.pm_cnt;
          break;
        case -3: // retry
          break;
        case -5: // async update
          if (!p->async_len) {
            lsb_terminate(p->sb->lsb, "cannot use async checkpointing without"
                          " a configured buffer");
            ret = 1;
          }
          // fall thru
        case -4: // batching
          ++p->sb->stats.pm_cnt;
          p->batching = true;
          break;
        default:
          lsb_terminate(p->sb->lsb, "invalid process_message return status");
          ret = 1;
          break;
        }

        // update the stats
        if (sample) {
          hs_update_running_stats(&p->sb->stats.mm, mmdelta);
          hs_update_running_stats(&p->sb->stats.pm, delta);
          p->sample = false;
          mmdelta = 0;
        }
        p->sb->stats.cur_memory = lsb_usage(p->sb->lsb, LSB_UT_MEMORY,
                                            LSB_US_CURRENT);
        p->sb->stats.max_memory = lsb_usage(p->sb->lsb, LSB_UT_MEMORY,
                                            LSB_US_MAXIMUM);
        p->sb->stats.max_output = lsb_usage(p->sb->lsb, LSB_UT_OUTPUT,
                                            LSB_US_MAXIMUM);
        p->sb->stats.max_instructions = lsb_usage(p->sb->lsb,
                                                  LSB_UT_INSTRUCTION,
                                                  LSB_US_MAXIMUM);
        pthread_mutex_unlock(&p->cp_lock);

        if (ret == -1) {
          const char* err = lsb_get_error(p->sb->lsb);
          if (strlen(err) > 0) {
            hs_log(g_module, 4, "file: %s received: %d %s", p->sb->name, ret,
                   lsb_get_error(p->sb->lsb));
          }
        }
      }
    }

    // advance the checkpoint if not batching/async
    if (ret <= 0 && !p->batching) {
      pthread_mutex_lock(&p->cp_lock);
      p->cp.input.id = p->cur.input.id;
      p->cp.input.offset = p->cur.input.offset;
      p->cp.analysis.id = p->cur.analysis.id;
      p->cp.analysis.offset = p->cur.analysis.offset;
      pthread_mutex_unlock(&p->cp_lock);
    }

    if (mmdelta) {
      pthread_mutex_lock(&p->cp_lock);
      hs_update_running_stats(&p->sb->stats.mm, mmdelta);
      p->sample = false;
      pthread_mutex_unlock(&p->cp_lock);
    }
  }

  if (ret <= 0 && p->sb->ticker_interval
      && current_t >= p->sb->next_timer_event) {
    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
    te_ret = hs_timer_event(p->sb->lsb, current_t);
    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts1);

    delta = hs_timespec_delta(&ts, &ts1);
    pthread_mutex_lock(&p->cp_lock);
    hs_update_running_stats(&p->sb->stats.te, delta);
    pthread_mutex_unlock(&p->cp_lock);

    p->sb->next_timer_event = current_t + p->sb->ticker_interval;
  }

  if (ret > 0 || te_ret > 0) {
    hs_log(g_module, 3, "terminated: %s msg: %s", p->sb->name,
           lsb_get_error(p->sb->lsb));
    return 1;
  }
  return ret;
}
Exemplo n.º 15
0
lsb_err_value lsb_init(lsb_lua_sandbox *lsb, const char *state_file)
{
  if (!lsb) {
    return LSB_ERR_UTIL_NULL;
  }

  if (lsb->state != LSB_UNKNOWN) {
    lsb_terminate(lsb, LSB_ERR_INIT);
    return LSB_ERR_INIT;
  }

  if (state_file && strlen(state_file) > 0) {
    lsb->state_file = malloc(strlen(state_file) + 1);
    if (!lsb->state_file) {
      lsb_terminate(lsb, LSB_ERR_UTIL_OOM);
      return LSB_ERR_UTIL_OOM;
    }
    strcpy(lsb->state_file, state_file);
  }

#ifndef LUA_JIT
  size_t mem_limit = lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT];
  lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT] = 0;
#endif

  preload_modules(lsb->lua);
  // load package module
  lua_pushcfunction(lsb->lua, luaopen_package);
  lua_pushstring(lsb->lua, LUA_LOADLIBNAME);
  lua_call(lsb->lua, 1, 1);
  lua_newtable(lsb->lua);
  lua_setmetatable(lsb->lua, -2);
  lua_pop(lsb->lua, 1);

  // load base module
  lua_getglobal(lsb->lua, "require");
  if (!lua_iscfunction(lsb->lua, -1)) {
    snprintf(lsb->error_message, LSB_ERROR_SIZE,
             "lsb_init() 'require' not found");
    lsb_terminate(lsb, NULL);
    return LSB_ERR_LUA;
  }
  lua_pushstring(lsb->lua, LUA_BASELIBNAME);
  if (lua_pcall(lsb->lua, 1, 0, 0)) {
    snprintf(lsb->error_message, LSB_ERROR_SIZE,
             "lsb_init %s", lua_tostring(lsb->lua, -1));
    lsb_terminate(lsb, NULL);
    return LSB_ERR_LUA;
  }

  if (lsb->usage[LSB_UT_INSTRUCTION][LSB_US_LIMIT] != 0) {
    lua_sethook(lsb->lua, instruction_manager, LUA_MASKCOUNT,
                (int)lsb->usage[LSB_UT_INSTRUCTION][LSB_US_LIMIT]);
  } else {
    lua_sethook(lsb->lua, NULL, 0, 0);
  }
#ifdef LUA_JIT
  // todo limit
  lua_gc(lsb->lua, LUA_GCSETMEMLIMIT,
         (int)lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT]);
#else
  lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT] = mem_limit;
#endif
  lua_CFunction pf = lua_atpanic(lsb->lua, unprotected_panic);
  int jump = setjmp(g_jbuf);
  if (jump || luaL_dofile(lsb->lua, lsb->lua_file) != 0) {
    int len = snprintf(lsb->error_message, LSB_ERROR_SIZE, "%s",
                       lua_tostring(lsb->lua, -1));
    if (len >= LSB_ERROR_SIZE || len < 0) {
      lsb->error_message[LSB_ERROR_SIZE - 1] = 0;
    }
    lsb_terminate(lsb, NULL);
    return LSB_ERR_LUA;
  } else {
    lua_gc(lsb->lua, LUA_GCCOLLECT, 0);
    lsb->usage[LSB_UT_INSTRUCTION][LSB_US_CURRENT] = instruction_usage(lsb);
    if (lsb->usage[LSB_UT_INSTRUCTION][LSB_US_CURRENT]
        > lsb->usage[LSB_UT_INSTRUCTION][LSB_US_MAXIMUM]) {
      lsb->usage[LSB_UT_INSTRUCTION][LSB_US_MAXIMUM] =
          lsb->usage[LSB_UT_INSTRUCTION][LSB_US_CURRENT];
    }
    lsb->state = LSB_RUNNING;
    if (lsb->state_file) {
      lsb_err_value ret = restore_global_data(lsb);
      if (ret) return ret;
    }
  }
  lua_atpanic(lsb->lua, pf);
  return NULL;
}