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

taosdata / TDengine / #3646

12 Mar 2025 12:34PM UTC coverage: 28.375% (-27.8%) from 56.156%
#3646

push

travis-ci

web-flow
Merge pull request #30119 from taosdata/ciup30

ci: Update workflow to fix param issue of run_tdgpt_test

59085 of 286935 branches covered (20.59%)

Branch coverage included in aggregate %.

102775 of 283490 relevant lines covered (36.25%)

55149.72 hits per line

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

54.41
/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 *taosMemMalloc(int64_t size) {
21,847,541✔
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)) {
278
    uint32_t r = taosRand() % tsRandErrDivisor;
279
    if ((r + 1) <= tsRandErrChance) {
280
      terrno = TSDB_CODE_OUT_OF_MEMORY;
281
      return NULL;
282
    }
283
  }
284
#endif
285
  void *p = malloc(size);
21,847,541✔
286
  if (NULL == p) {
21,847,541!
287
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
288
  }
289
  return p;
21,847,541✔
290
#endif
291
}
292

293
void *taosMemCalloc(int64_t num, int64_t size) {
33,956,020✔
294
#ifdef USE_TD_MEMORY
295
  int32_t memorySize = num * size;
296
  char   *tmp = calloc(memorySize + sizeof(TdMemoryInfo), 1);
297
  if (tmp == NULL) {
298
    terrno = TSDB_CODE_OUT_OF_MEMORY;
299
    return NULL;
300
  }
301

302
  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)tmp;
303
  pTdMemoryInfo->memorySize = memorySize;
304
  pTdMemoryInfo->symbol = TD_MEMORY_SYMBOL;
305
  taosBackTrace(pTdMemoryInfo->stackTrace, TD_MEMORY_STACK_TRACE_DEPTH);
306

307
  return (char *)tmp + sizeof(TdMemoryInfo);
308
#else
309
#ifdef BUILD_WITH_RAND_ERR
310
  if (tsEnableRandErr && (tsRandErrScope & RAND_ERR_MEMORY)) {
311
    uint32_t r = taosRand() % tsRandErrDivisor;
312
    if ((r + 1) <= tsRandErrChance) {
313
      terrno = TSDB_CODE_OUT_OF_MEMORY;
314
      uError("random memory error: %s, %s", tstrerror(terrno), __func__);
315
      return NULL;
316
    }
317
  }
318
#endif
319

320
  void *p = calloc(num, size);
33,956,020✔
321
  if (NULL == p) {
33,956,020!
322
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
323
  }
324
  return p;
33,956,020✔
325
#endif
326
}
327

328
void *taosMemRealloc(void *ptr, int64_t size) {
1,545,350✔
329
#ifdef USE_TD_MEMORY
330
  if (ptr == NULL) return taosMemoryMalloc(size);
331

332
  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo));
333
  if (tpTdMemoryInfo->symbol != TD_MEMORY_SYMBOL) {
334
    terrno = TSDB_CODE_OUT_OF_MEMORY;
335
    return NULL;
336
  }
337

338
  TdMemoryInfo tdMemoryInfo;
339
  memcpy(&tdMemoryInfo, pTdMemoryInfo, sizeof(TdMemoryInfo));
340

341
  void *tmp = realloc(pTdMemoryInfo, size + sizeof(TdMemoryInfo));
342
  if (tmp == NULL) {
343
    terrno = TSDB_CODE_OUT_OF_MEMORY;
344
    return NULL;
345
  }
346

347
  memcpy(tmp, &tdMemoryInfo, sizeof(TdMemoryInfo));
348
  ((TdMemoryInfoPtr)tmp)->memorySize = size;
349

350
  return (char *)tmp + sizeof(TdMemoryInfo);
351
#else
352
#ifdef BUILD_WITH_RAND_ERR
353
  if (tsEnableRandErr && (tsRandErrScope & RAND_ERR_MEMORY)) {
354
    uint32_t r = taosRand() % tsRandErrDivisor;
355
    if ((r + 1) <= tsRandErrChance) {
356
      terrno = TSDB_CODE_OUT_OF_MEMORY;
357
      return NULL;
358
    }
359
  }
360
#endif
361

362
  void *p = realloc(ptr, size);
1,545,350✔
363
  if (size > 0 && NULL == p) {
1,545,350!
364
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
365
  }
366
  return p;
1,545,350✔
367
#endif
368
}
369

370
char *taosStrdupi(const char *ptr) {
1,465,638✔
371
#ifdef USE_TD_MEMORY
372
  if (ptr == NULL) return NULL;
373

374
  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo));
375
  if (pTdMemoryInfo->symbol != TD_MEMORY_SYMBOL) {
376
    return NULL;
377
  }
378
  void *tmp = tstrdup(pTdMemoryInfo);
379
  if (tmp == NULL) return NULL;
380

381
  memcpy(tmp, pTdMemoryInfo, sizeof(TdMemoryInfo));
382
  taosBackTrace(((TdMemoryInfoPtr)tmp)->stackTrace, TD_MEMORY_STACK_TRACE_DEPTH);
383

384
  return (char *)tmp + sizeof(TdMemoryInfo);
385
#else
386
#ifdef BUILD_WITH_RAND_ERR
387
  if (tsEnableRandErr && (tsRandErrScope & RAND_ERR_MEMORY)) {
388
    uint32_t r = taosRand() % tsRandErrDivisor;
389
    if ((r + 1) <= tsRandErrChance) {
390
      terrno = TSDB_CODE_OUT_OF_MEMORY;
391
      return NULL;
392
    }
393
  }
394
#endif
395

396
  return tstrdup(ptr);
1,465,638✔
397
#endif
398
}
399

400

401
void taosMemFree(void *ptr) {
61,969,605✔
402
  if (NULL == ptr) return;
61,969,605✔
403
#ifdef USE_TD_MEMORY
404
  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo));
405
  if (pTdMemoryInfo->symbol == TD_MEMORY_SYMBOL) {
406
    pTdMemoryInfo->memorySize = 0;
407
    // memset(pTdMemoryInfo, 0, sizeof(TdMemoryInfo));
408
    free(pTdMemoryInfo);
409
  } else {
410
    free(ptr);
411
  }
412
#else
413
  return free(ptr);
58,632,364✔
414
#endif
415
}
416

417
int64_t taosMemSize(void *ptr) {
21,617✔
418
  if (ptr == NULL) return 0;
21,617!
419

420
#ifdef USE_TD_MEMORY
421
  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo));
422
  if (pTdMemoryInfo->symbol != TD_MEMORY_SYMBOL) {
423
    return NULL;
424
  }
425

426
  return pTdMemoryInfo->memorySize;
427
#else
428
#ifdef WINDOWS
429
  return _msize(ptr);
430
#elif defined(_TD_DARWIN_64)
431
  return malloc_size(ptr);
432
#else
433
  return malloc_usable_size(ptr);
21,617✔
434
#endif
435
#endif
436
}
437

438
int32_t taosMemTrim(int32_t size, bool* trimed) {
505✔
439
#if defined(WINDOWS) || defined(DARWIN) || defined(_ALPINE)
440
  // do nothing
441
  return TSDB_CODE_SUCCESS;
442
#else
443
  if (trimed) {
505!
444
    *trimed = malloc_trim(size);
×
445
  } else {
446
    malloc_trim(size);
505✔
447
  }
448
  
449
  return TSDB_CODE_SUCCESS;
505✔
450
#endif
451
}
452

453
void *taosMemMallocAlign(uint32_t alignment, int64_t size) {
195,741✔
454
#ifdef USE_TD_MEMORY
455
  return NULL;
456
#else
457
#if defined(LINUX)
458
#ifdef BUILD_WITH_RAND_ERR
459
  if (tsEnableRandErr && (tsRandErrScope & RAND_ERR_MEMORY)) {
460
    uint32_t r = taosRand() % tsRandErrDivisor;
461
    if ((r + 1) <= tsRandErrChance) {
462
      terrno = TSDB_CODE_OUT_OF_MEMORY;
463
      return NULL;
464
    }
465
  }
466
#endif
467

468
  void *p = memalign(alignment, size);
195,741✔
469
  if (NULL == p) {
195,847!
470
    if (ENOMEM == errno) {
×
471
      terrno = TSDB_CODE_OUT_OF_MEMORY;
×
472
    } else {
473
      terrno = TAOS_SYSTEM_ERROR(errno);
×
474
    }
475
  }
476
  return p;
195,847✔
477
#else
478
  return taosMemMalloc(size);
479
#endif
480
#endif
481
}
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