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

taosdata / TDengine / #3533

20 Nov 2024 07:11AM UTC coverage: 58.848% (-1.9%) from 60.78%
#3533

push

travis-ci

web-flow
Merge pull request #28823 from taosdata/fix/3.0/TD-32587

fix:[TD-32587]fix stmt segmentation fault

115578 of 252434 branches covered (45.79%)

Branch coverage included in aggregate %.

1 of 4 new or added lines in 1 file covered. (25.0%)

8038 existing lines in 233 files now uncovered.

194926 of 275199 relevant lines covered (70.83%)

1494459.59 hits per line

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

63.71
/source/os/src/osMemory.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15

16
#define ALLOW_FORBID_FUNC
17
#ifdef _TD_DARWIN_64
18
#include <malloc/malloc.h>
19
#else
20
#include <malloc.h>
21
#endif
22
#include "os.h"
23
#include "tdef.h"
24

25
int32_t          tsRandErrChance = 1;
26
int64_t          tsRandErrDivisor = 10001;
27
int64_t          tsRandErrScope = (RAND_ERR_MEMORY | RAND_ERR_FILE | RAND_ERR_NETWORK);
28
threadlocal bool tsEnableRandErr = 0;
29

30
#if defined(USE_TD_MEMORY) || defined(USE_ADDR2LINE)
31

32
#define TD_MEMORY_SYMBOL ('T' << 24 | 'A' << 16 | 'O' << 8 | 'S')
33

34
#define TD_MEMORY_STACK_TRACE_DEPTH 10
35

36
typedef struct TdMemoryInfo *TdMemoryInfoPtr;
37

38
typedef struct TdMemoryInfo {
39
  int32_t symbol;
40
  int32_t memorySize;
41
  void   *stackTrace[TD_MEMORY_STACK_TRACE_DEPTH];  // gdb: disassemble /m 0xXXX
42
  // TdMemoryInfoPtr pNext;
43
  // TdMemoryInfoPtr pPrev;
44
} TdMemoryInfo;
45

46
// static TdMemoryInfoPtr GlobalMemoryPtr = NULL;
47

48
#ifdef WINDOWS
49
#define tstrdup(str) _strdup(str)
50

51
int32_t taosBackTrace(void **buffer, int32_t size) {
52
  int32_t frame = 0;
53
  return frame;
54
}
55

56
#ifdef USE_ADDR2LINE
57
#include <DbgHelp.h>
58
#pragma comment(lib, "dbghelp.lib")
59

60
void taosPrintBackTrace() {
61
#define MAX_STACK_FRAMES 20
62

63
  void *pStack[MAX_STACK_FRAMES];
64

65
  HANDLE process = GetCurrentProcess();
66
  SymInitialize(process, NULL, TRUE);
67
  WORD frames = CaptureStackBackTrace(1, MAX_STACK_FRAMES, pStack, NULL);
68

69
  char buf_tmp[1024];
70
  for (WORD i = 0; i < frames; ++i) {
71
    DWORD64 address = (DWORD64)(pStack[i]);
72

73
    DWORD64      displacementSym = 0;
74
    char         buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
75
    PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
76
    pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
77
    pSymbol->MaxNameLen = MAX_SYM_NAME;
78

79
    DWORD           displacementLine = 0;
80
    IMAGEHLP_LINE64 line;
81
    // SymSetOptions(SYMOPT_LOAD_LINES);
82
    line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
83

84
    if (SymFromAddr(process, address, &displacementSym, pSymbol) &&
85
        SymGetLineFromAddr64(process, address, &displacementLine, &line)) {
86
      snprintf(buf_tmp, sizeof(buf_tmp), "BackTrace %08" PRId64 " %s:%d %s\n", taosGetSelfPthreadId(), line.FileName,
87
               line.LineNumber, pSymbol->Name);
88
    } else {
89
      snprintf(buf_tmp, sizeof(buf_tmp), "BackTrace error: %d\n", GetLastError());
90
    }
91
    write(1, buf_tmp, strlen(buf_tmp));
92
  }
93
}
94
#endif
95
#else
96
#define tstrdup(str) strdup(str)
97

98
#include <execinfo.h>
99

100
#define STACKCALL __attribute__((regparm(1), noinline))
101
void **STACKCALL taosGetEbp(void) {
102
  void **ebp = NULL;
103
  __asm__ __volatile__("mov %%rbp, %0;\n\t"
104
                       : "=m"(ebp)  /* output */
105
                       :            /* input */
106
                       : "memory"); /* not affect register */
107
  return (void **)(*ebp);
108
}
109

110
int32_t taosBackTrace(void **buffer, int32_t size) {
111
  int32_t frame = 0;
112
  void  **ebp;
113
  void  **ret = NULL;
114
  size_t  func_frame_distance = 0;
115
  if (buffer != NULL && size > 0) {
116
    ebp = taosGetEbp();
117
    func_frame_distance = (size_t)*ebp - (size_t)ebp;
118
    while (ebp && frame < size && (func_frame_distance < (1ULL << 24))  // assume function ebp more than 16M
119
           && (func_frame_distance > 0)) {
120
      ret = ebp + 1;
121
      buffer[frame++] = *ret;
122
      ebp = (void **)(*ebp);
123
      func_frame_distance = (size_t)*ebp - (size_t)ebp;
124
    }
125
  }
126
  return frame;
127
}
128

129
// char **taosBackTraceSymbols(int32_t *size) {
130
//   void  *buffer[20] = {NULL};
131
//   *size = taosBackTrace(buffer, 20);
132
//   return backtrace_symbols(buffer, *size);
133
// }
134

135
#ifdef USE_ADDR2LINE
136

137
#include "dwarf.h"
138
#include "libdwarf.h"
139
#include "osThread.h"
140

141
#define DW_PR_DUu "llu"
142

143
typedef struct lookup_table {
144
  Dwarf_Line         *table;
145
  Dwarf_Line_Context *ctxts;
146
  int                 cnt;
147
  Dwarf_Addr          low;
148
  Dwarf_Addr          high;
149
} lookup_tableT;
150

151
extern int  create_lookup_table(Dwarf_Debug dbg, lookup_tableT *lookup_table);
152
extern void delete_lookup_table(lookup_tableT *lookup_table);
153

154
size_t              addr = 0;
155
lookup_tableT       lookup_table;
156
Dwarf_Debug         tDbg;
157
static TdThreadOnce traceThreadInit = PTHREAD_ONCE_INIT;
158

159
void endTrace() {
160
  TdThreadOnce tmp = PTHREAD_ONCE_INIT;
161
  if (memcmp(&traceThreadInit, &tmp, sizeof(TdThreadOnce)) != 0) {
162
    delete_lookup_table(&lookup_table);
163
    dwarf_finish(tDbg);
164
  }
165
}
166
void startTrace() {
167
  int       ret;
168
  Dwarf_Ptr errarg = 0;
169

170
  FILE *fp = fopen("/proc/self/maps", "r");
171
  ret = fscanf(fp, "%lx-", &addr);
172
  fclose(fp);
173

174
  ret = dwarf_init_path("/proc/self/exe", NULL, 0, DW_GROUPNUMBER_ANY, NULL, errarg, &tDbg, NULL);
175
  if (ret == DW_DLV_NO_ENTRY) {
176
    printf("Unable to open file");
177
    return;
178
  }
179

180
  ret = create_lookup_table(tDbg, &lookup_table);
181
  if (ret != DW_DLV_OK) {
182
    printf("Unable to create lookup table");
183
    return;
184
  }
185
  atexit(endTrace);
186
}
187
static void print_line(Dwarf_Debug dbg, Dwarf_Line line, Dwarf_Addr pc) {
188
  char          *linesrc = "??";
189
  Dwarf_Unsigned lineno = 0;
190

191
  if (line) {
192
    dwarf_linesrc(line, &linesrc, NULL);
193
    dwarf_lineno(line, &lineno, NULL);
194
  }
195
  (void)printf("BackTrace %08" PRId64 " %s:%" DW_PR_DUu "\n", taosGetSelfPthreadId(), linesrc, lineno);
196
  if (line) dwarf_dealloc(dbg, linesrc, DW_DLA_STRING);
197
}
198
void taosPrintBackTrace() {
199
  int        size = 20;
200
  void     **buffer[20];
201
  Dwarf_Addr pc;
202
  int32_t    frame = 0;
203
  void     **ebp;
204
  void     **ret = NULL;
205
  size_t     func_frame_distance = 0;
206

207
  taosThreadOnce(&traceThreadInit, startTrace);
208

209
  if (buffer != NULL && size > 0) {
210
    ebp = taosGetEbp();
211
    func_frame_distance = (size_t)*ebp - (size_t)ebp;
212
    while (ebp && frame < size && (func_frame_distance < (1ULL << 24)) && (func_frame_distance > 0)) {
213
      ret = ebp + 1;
214
      buffer[frame++] = *ret;
215
      ebp = (void **)(*ebp);
216
      func_frame_distance = (size_t)*ebp - (size_t)ebp;
217
    }
218
    for (size_t i = 0; i < frame; i++) {
219
      pc = (size_t)buffer[i] - addr;
220
      if (pc > 0) {
221
        if (pc >= lookup_table.low && pc < lookup_table.high) {
222
          Dwarf_Line line = lookup_table.table[pc - lookup_table.low];
223
          if (line) print_line(tDbg, line, pc);
224
        }
225
      }
226
    }
227
  }
228
}
229
#endif
230
#endif
231
#endif
232

233
#ifndef USE_ADDR2LINE
234
void taosPrintBackTrace() { return; }
×
235
#endif
236

237
int32_t taosMemoryDbgInit() {
×
238
#if defined(LINUX) && !defined(_ALPINE)
239
  int ret = mallopt(M_MMAP_THRESHOLD, 0);
×
240
  if (0 == ret) {
×
241
    return TAOS_SYSTEM_ERROR(errno);
×
242
  }
243

244
  return 0;
×
245
#else
246
  return TSDB_CODE_FAILED;
247
#endif
248
}
249

250
int32_t taosMemoryDbgInitRestore() {
×
251
#if defined(LINUX) && !defined(_ALPINE)
252
  int ret = mallopt(M_MMAP_THRESHOLD, 128 * 1024);
×
253
  if (0 == ret) {
×
254
    return TAOS_SYSTEM_ERROR(errno);
×
255
  }
256

257
  return 0;
×
258
#else
259
  return TSDB_CODE_FAILED;
260
#endif
261
}
262

263
void *taosMemoryMalloc(int64_t size) {
323,109,525✔
264
#ifdef USE_TD_MEMORY
265
  void *tmp = malloc(size + sizeof(TdMemoryInfo));
266
  if (tmp == NULL) return NULL;
267

268
  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)tmp;
269
  pTdMemoryInfo->memorySize = size;
270
  pTdMemoryInfo->symbol = TD_MEMORY_SYMBOL;
271
  taosBackTrace(pTdMemoryInfo->stackTrace, TD_MEMORY_STACK_TRACE_DEPTH);
272

273
  return (char *)tmp + sizeof(TdMemoryInfo);
274
#else
275

276
#ifdef BUILD_WITH_RAND_ERR
277
  if (tsEnableRandErr && (tsRandErrScope & RAND_ERR_MEMORY)) {
323,109,525!
278
    uint32_t r = taosRand() % tsRandErrDivisor;
48,754,471✔
279
    if ((r + 1) <= tsRandErrChance) {
48,842,402!
UNCOV
280
      terrno = TSDB_CODE_OUT_OF_MEMORY;
×
281
      return NULL;
4,919✔
282
    }
283
  }
284
#endif
285
  void *p = malloc(size);
323,334,957✔
286
  if (NULL == p) {
323,334,957!
287
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
288
  }
289
  return p;
323,334,957✔
290
#endif
291
}
292

293
void *taosMemoryCalloc(int64_t num, int64_t size) {
417,966,893✔
294
#ifdef USE_TD_MEMORY
295
  int32_t memorySize = num * size;
296
  char   *tmp = calloc(memorySize + sizeof(TdMemoryInfo), 1);
297
  if (tmp == NULL) return NULL;
298

299
  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)tmp;
300
  pTdMemoryInfo->memorySize = memorySize;
301
  pTdMemoryInfo->symbol = TD_MEMORY_SYMBOL;
302
  taosBackTrace(pTdMemoryInfo->stackTrace, TD_MEMORY_STACK_TRACE_DEPTH);
303

304
  return (char *)tmp + sizeof(TdMemoryInfo);
305
#else
306
#ifdef BUILD_WITH_RAND_ERR
307
  if (tsEnableRandErr && (tsRandErrScope & RAND_ERR_MEMORY)) {
417,966,893!
308
    uint32_t r = taosRand() % tsRandErrDivisor;
79,124,306✔
309
    if ((r + 1) <= tsRandErrChance) {
79,236,775!
UNCOV
310
      terrno = TSDB_CODE_OUT_OF_MEMORY;
×
311
      uError("random memory error: %s, %s", tstrerror(terrno), __func__);
7,769!
312
      return NULL;
7,769✔
313
    }
314
  }
315
#endif
316

317
  void *p = calloc(num, size);
418,104,503✔
318
  if (NULL == p) {
418,104,503!
319
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
320
  }
321
  return p;
418,104,503✔
322
#endif
323
}
324

325
void *taosMemoryRealloc(void *ptr, int64_t size) {
35,006,089✔
326
#ifdef USE_TD_MEMORY
327
  if (ptr == NULL) return taosMemoryMalloc(size);
328

329
  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo));
330
  if (tpTdMemoryInfo->symbol != TD_MEMORY_SYMBOL) {
331
    return NULL;
332
  }
333

334
  TdMemoryInfo tdMemoryInfo;
335
  memcpy(&tdMemoryInfo, pTdMemoryInfo, sizeof(TdMemoryInfo));
336

337
  void *tmp = realloc(pTdMemoryInfo, size + sizeof(TdMemoryInfo));
338
  if (tmp == NULL) return NULL;
339

340
  memcpy(tmp, &tdMemoryInfo, sizeof(TdMemoryInfo));
341
  ((TdMemoryInfoPtr)tmp)->memorySize = size;
342

343
  return (char *)tmp + sizeof(TdMemoryInfo);
344
#else
345
#ifdef BUILD_WITH_RAND_ERR
346
  if (tsEnableRandErr && (tsRandErrScope & RAND_ERR_MEMORY)) {
35,006,089!
347
    uint32_t r = taosRand() % tsRandErrDivisor;
25,932,244✔
348
    if ((r + 1) <= tsRandErrChance) {
25,964,492✔
349
      terrno = TSDB_CODE_OUT_OF_MEMORY;
1,668✔
350
      return NULL;
2,562✔
351
    }
352
  }
353
#endif
354

355
  void *p = realloc(ptr, size);
35,036,669✔
356
  if (size > 0 && NULL == p) {
35,036,669!
357
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
358
  }
359
  return p;
35,036,669✔
360
#endif
361
}
362

363
char *taosStrdup(const char *ptr) {
11,733,556✔
364
#ifdef USE_TD_MEMORY
365
  if (ptr == NULL) return NULL;
366

367
  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo));
368
  if (pTdMemoryInfo->symbol != TD_MEMORY_SYMBOL) {
369
    return NULL;
370
  }
371
  void *tmp = tstrdup(pTdMemoryInfo);
372
  if (tmp == NULL) return NULL;
373

374
  memcpy(tmp, pTdMemoryInfo, sizeof(TdMemoryInfo));
375
  taosBackTrace(((TdMemoryInfoPtr)tmp)->stackTrace, TD_MEMORY_STACK_TRACE_DEPTH);
376

377
  return (char *)tmp + sizeof(TdMemoryInfo);
378
#else
379
#ifdef BUILD_WITH_RAND_ERR
380
  if (tsEnableRandErr && (tsRandErrScope & RAND_ERR_MEMORY)) {
11,733,556!
381
    uint32_t r = taosRand() % tsRandErrDivisor;
1,797,870✔
382
    if ((r + 1) <= tsRandErrChance) {
1,798,216✔
383
      terrno = TSDB_CODE_OUT_OF_MEMORY;
162✔
384
      return NULL;
162✔
385
    }
386
  }
387
#endif
388

389
  return tstrdup(ptr);
11,733,740✔
390
#endif
391
}
392

393
void taosMemoryFree(void *ptr) {
818,944,132✔
394
  if (NULL == ptr) return;
818,944,132✔
395
#ifdef USE_TD_MEMORY
396
  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo));
397
  if (pTdMemoryInfo->symbol == TD_MEMORY_SYMBOL) {
398
    pTdMemoryInfo->memorySize = 0;
399
    // memset(pTdMemoryInfo, 0, sizeof(TdMemoryInfo));
400
    free(pTdMemoryInfo);
401
  } else {
402
    free(ptr);
403
  }
404
#else
405
  return free(ptr);
803,830,333✔
406
#endif
407
}
408

409
int64_t taosMemorySize(void *ptr) {
×
410
  if (ptr == NULL) return 0;
×
411

412
#ifdef USE_TD_MEMORY
413
  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo));
414
  if (pTdMemoryInfo->symbol != TD_MEMORY_SYMBOL) {
415
    return NULL;
416
  }
417

418
  return pTdMemoryInfo->memorySize;
419
#else
420
#ifdef WINDOWS
421
  return _msize(ptr);
422
#elif defined(_TD_DARWIN_64)
423
  return malloc_size(ptr);
424
#else
425
  return malloc_usable_size(ptr);
×
426
#endif
427
#endif
428
}
429

UNCOV
430
void taosMemoryTrim(int32_t size) {
×
431
#if defined(WINDOWS) || defined(DARWIN) || defined(_ALPINE)
432
  // do nothing
433
  return;
434
#else
UNCOV
435
  (void)malloc_trim(size);
×
436
#endif
UNCOV
437
}
×
438

439
void *taosMemoryMallocAlign(uint32_t alignment, int64_t size) {
8,822,510✔
440
#ifdef USE_TD_MEMORY
441
  return NULL;
442
#else
443
#if defined(LINUX)
444
#ifdef BUILD_WITH_RAND_ERR
445
  if (tsEnableRandErr && (tsRandErrScope & RAND_ERR_MEMORY)) {
8,822,510!
446
    uint32_t r = taosRand() % tsRandErrDivisor;
6,145,799✔
447
    if ((r + 1) <= tsRandErrChance) {
6,147,556✔
448
      terrno = TSDB_CODE_OUT_OF_MEMORY;
590✔
449
      return NULL;
590✔
450
    }
451
  }
452
#endif
453

454
  void *p = memalign(alignment, size);
8,823,677✔
455
  if (NULL == p) {
8,823,985!
456
    if (ENOMEM == errno) {
×
457
      terrno = TSDB_CODE_OUT_OF_MEMORY;
×
458
    } else {
459
      terrno = TAOS_SYSTEM_ERROR(errno);
×
460
    }
461
  }
462
  return p;
8,823,985✔
463
#else
464
  return taosMemoryMalloc(size);
465
#endif
466
#endif
467
}
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

© 2026 Coveralls, Inc