• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tarantool / luajit / 10774454435

09 Sep 2024 01:39PM UTC coverage: 92.806% (-0.08%) from 92.882%
10774454435

push

github

Buristan
FFI: Drop finalizer table rehash after GC cycle.

Reported by Sergey Kaplun.

(cherry picked from commit fb22d0f80)

The raising of the OOM error when rehashing the finalizer table (when we
can't allocate a new hash part) leads to crashes in either
`lj_trace_exit()` or `lj_trace_unwind()` due to unprotected error
raising, which either has no DWARF eh_frame [1] or loses the context of
the JIT compiler.

This patch drops rehashing of the cdata finalizer table to avoid these
crashes. It will prevent the cdata finalizer table from shrinking when a
huge amount of the cdata objects is collected by the GC. OTOH, the
finzlizer table most probably will grow anyway to the old size, so this
is not crucial.

Sergey Kaplun:
* added the description and the test for the problem

[1]: https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html

Part of tarantool/tarantool#10199
Resolves tarantool/tarantool#10290

5681 of 6025 branches covered (94.29%)

Branch coverage included in aggregate %.

21655 of 23430 relevant lines covered (92.42%)

2945096.28 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.21
/src/lj_load.c
1
/*
2
** Load and dump code.
3
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
4
*/
5

6
#include <errno.h>
7
#include <stdio.h>
8

9
#define lj_load_c
10
#define LUA_CORE
11

12
#include "lua.h"
13
#include "lauxlib.h"
14

15
#include "lj_obj.h"
16
#include "lj_gc.h"
17
#include "lj_err.h"
18
#include "lj_buf.h"
19
#include "lj_func.h"
20
#include "lj_frame.h"
21
#include "lj_vm.h"
22
#include "lj_lex.h"
23
#include "lj_bcdump.h"
24
#include "lj_parse.h"
25

26
/* -- Load Lua source code and bytecode ----------------------------------- */
27

28
static TValue *cpparser(lua_State *L, lua_CFunction dummy, void *ud)
53,610✔
29
{
30
  LexState *ls = (LexState *)ud;
53,610✔
31
  GCproto *pt;
53,610✔
32
  GCfunc *fn;
53,610✔
33
  int bc;
53,610✔
34
  UNUSED(dummy);
53,610✔
35
  cframe_errfunc(L->cframe) = -1;  /* Inherit error function. */
53,610✔
36
  bc = lj_lex_setup(L, ls);
53,610✔
37
  if (ls->mode && !strchr(ls->mode, bc ? 'b' : 't')) {
53,610✔
38
    setstrV(L, L->top++, lj_err_str(L, LJ_ERR_XMODE));
×
39
    lj_err_throw(L, LUA_ERRSYNTAX);
×
40
  }
41
  pt = bc ? lj_bcread(ls) : lj_parse(ls);
53,608✔
42
  fn = lj_func_newL_empty(L, pt, tabref(L->env));
40,893✔
43
  /* Don't combine above/below into one statement. */
44
  setfuncV(L, L->top++, fn);
40,893✔
45
  return NULL;
40,893✔
46
}
47

48
LUA_API int lua_loadx(lua_State *L, lua_Reader reader, void *data,
53,610✔
49
                      const char *chunkname, const char *mode)
50
{
51
  LexState ls;
53,610✔
52
  int status;
53,610✔
53
  ls.rfunc = reader;
53,610✔
54
  ls.rdata = data;
53,610✔
55
  ls.chunkarg = chunkname ? chunkname : "?";
53,610✔
56
  ls.mode = mode;
53,610✔
57
  lj_buf_init(L, &ls.sb);
53,610✔
58
  status = lj_vm_cpcall(L, NULL, &ls, cpparser);
53,610✔
59
  lj_lex_cleanup(L, &ls);
53,610✔
60
  lj_gc_check(L);
53,610✔
61
  return status;
53,610✔
62
}
63

64
LUA_API int lua_load(lua_State *L, lua_Reader reader, void *data,
2✔
65
                     const char *chunkname)
66
{
67
  return lua_loadx(L, reader, data, chunkname, NULL);
2✔
68
}
69

70
typedef struct FileReaderCtx {
71
  FILE *fp;
72
  char buf[LUAL_BUFFERSIZE];
73
} FileReaderCtx;
74

75
static const char *reader_file(lua_State *L, void *ud, size_t *size)
2,714✔
76
{
77
  FileReaderCtx *ctx = (FileReaderCtx *)ud;
2,714✔
78
  UNUSED(L);
2,714✔
79
  if (feof(ctx->fp)) return NULL;
2,714✔
80
  *size = fread(ctx->buf, 1, sizeof(ctx->buf), ctx->fp);
1,598✔
81
  return *size > 0 ? ctx->buf : NULL;
1,598✔
82
}
83

84
LUALIB_API int luaL_loadfilex(lua_State *L, const char *filename,
1,129✔
85
                              const char *mode)
86
{
87
  FileReaderCtx ctx;
1,129✔
88
  int status;
1,129✔
89
  const char *chunkname;
1,129✔
90
  if (filename) {
1,129✔
91
    ctx.fp = fopen(filename, "rb");
1,122✔
92
    if (ctx.fp == NULL) {
1,122✔
93
      lua_pushfstring(L, "cannot open %s: %s", filename, strerror(errno));
4✔
94
      return LUA_ERRFILE;
4✔
95
    }
96
    chunkname = lua_pushfstring(L, "@%s", filename);
1,118✔
97
  } else {
98
    ctx.fp = stdin;
7✔
99
    chunkname = "=stdin";
7✔
100
  }
101
  status = lua_loadx(L, reader_file, &ctx, chunkname, mode);
1,125✔
102
  if (ferror(ctx.fp)) {
1,125✔
103
    L->top -= filename ? 2 : 1;
×
104
    lua_pushfstring(L, "cannot read %s: %s", chunkname+1, strerror(errno));
×
105
    if (filename)
×
106
      fclose(ctx.fp);
×
107
    return LUA_ERRFILE;
×
108
  }
109
  if (filename) {
1,125✔
110
    L->top--;
1,118✔
111
    copyTV(L, L->top-1, L->top);
1,118✔
112
    fclose(ctx.fp);
1,118✔
113
  }
114
  return status;
115
}
116

117
LUALIB_API int luaL_loadfile(lua_State *L, const char *filename)
1,087✔
118
{
119
  return luaL_loadfilex(L, filename, NULL);
1,087✔
120
}
121

122
typedef struct StringReaderCtx {
123
  const char *str;
124
  size_t size;
125
} StringReaderCtx;
126

127
static const char *reader_string(lua_State *L, void *ud, size_t *size)
95,401✔
128
{
129
  StringReaderCtx *ctx = (StringReaderCtx *)ud;
95,401✔
130
  UNUSED(L);
95,401✔
131
  if (ctx->size == 0) return NULL;
95,401✔
132
  *size = ctx->size;
52,317✔
133
  ctx->size = 0;
52,317✔
134
  return ctx->str;
52,317✔
135
}
136

137
LUALIB_API int luaL_loadbufferx(lua_State *L, const char *buf, size_t size,
52,326✔
138
                                const char *name, const char *mode)
139
{
140
  StringReaderCtx ctx;
52,326✔
141
  ctx.str = buf;
52,326✔
142
  ctx.size = size;
52,326✔
143
  return lua_loadx(L, reader_string, &ctx, name, mode);
51,905✔
144
}
145

146
LUALIB_API int luaL_loadbuffer(lua_State *L, const char *buf, size_t size,
421✔
147
                               const char *name)
148
{
149
  return luaL_loadbufferx(L, buf, size, name, NULL);
416✔
150
}
151

152
LUALIB_API int luaL_loadstring(lua_State *L, const char *s)
5✔
153
{
154
  return luaL_loadbuffer(L, s, strlen(s), s);
5✔
155
}
156

157
/* -- Dump bytecode ------------------------------------------------------- */
158

159
LUA_API int lua_dump(lua_State *L, lua_Writer writer, void *data)
×
160
{
161
  cTValue *o = L->top-1;
×
162
  lj_checkapi(L->top > L->base, "top slot empty");
×
163
  if (tvisfunc(o) && isluafunc(funcV(o)))
×
164
    return lj_bcwrite(L, funcproto(funcV(o)), writer, data, 0);
×
165
  else
166
    return 1;
167
}
168

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc