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

taosdata / TDengine / #3523

06 Nov 2024 02:29AM UTC coverage: 55.861% (-2.4%) from 58.216%
#3523

push

travis-ci

web-flow
Merge pull request #28551 from taosdata/feat/TS-5215-2

test(blob): testing & fixes for blob

106075 of 245834 branches covered (43.15%)

Branch coverage included in aggregate %.

0 of 15 new or added lines in 2 files covered. (0.0%)

17003 existing lines in 254 files now uncovered.

181910 of 269703 relevant lines covered (67.45%)

1527639.59 hits per line

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

65.32
/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) {
321,230,473✔
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)) {
321,230,473!
278
    uint32_t r = taosRand() % tsRandErrDivisor;
35,226,155✔
279
    if ((r + 1) <= tsRandErrChance) {
35,308,822!
UNCOV
280
      terrno = TSDB_CODE_OUT_OF_MEMORY;
×
281
      return NULL;
1,488✔
282
    }
283
  }
284
#endif
285
  void *p = malloc(size);
321,496,362✔
286
  if (NULL == p) {
321,496,362!
287
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
288
  }
289
  return p;
321,496,362✔
290
#endif
291
}
292

293
void *taosMemoryCalloc(int64_t num, int64_t size) {
495,635,374✔
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)) {
495,635,374!
308
    uint32_t r = taosRand() % tsRandErrDivisor;
62,142,899✔
309
    if ((r + 1) <= tsRandErrChance) {
62,337,784!
UNCOV
310
      terrno = TSDB_CODE_OUT_OF_MEMORY;
×
311
      uError("random memory error: %s, %s", tstrerror(terrno), __func__);
3,640!
312
      return NULL;
3,640✔
313
    }
314
  }
315
#endif
316

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

325
void *taosMemoryRealloc(void *ptr, int64_t size) {
33,301,258✔
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)) {
33,301,258!
347
    uint32_t r = taosRand() % tsRandErrDivisor;
28,142,313✔
348
    if ((r + 1) <= tsRandErrChance) {
28,208,628✔
349
      terrno = TSDB_CODE_OUT_OF_MEMORY;
13,488✔
350
      return NULL;
986✔
351
    }
352
  }
353
#endif
354

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

363
char *taosStrdup(const char *ptr) {
14,917,191✔
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)) {
14,917,191!
381
    uint32_t r = taosRand() % tsRandErrDivisor;
1,128,267✔
382
    if ((r + 1) <= tsRandErrChance) {
1,129,396✔
383
      terrno = TSDB_CODE_OUT_OF_MEMORY;
55✔
384
      return NULL;
55✔
385
    }
386
  }
387
#endif
388

389
  return tstrdup(ptr);
14,918,265✔
390
#endif
391
}
392

393
void taosMemoryFree(void *ptr) {
902,742,301✔
394
  if (NULL == ptr) return;
902,742,301✔
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);
884,599,419✔
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

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

439
void *taosMemoryMallocAlign(uint32_t alignment, int64_t size) {
15,076,807✔
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)) {
15,076,807!
446
    uint32_t r = taosRand() % tsRandErrDivisor;
14,254,306✔
447
    if ((r + 1) <= tsRandErrChance) {
14,266,672✔
448
      terrno = TSDB_CODE_OUT_OF_MEMORY;
485✔
449
      return NULL;
485✔
450
    }
451
  }
452
#endif
453

454
  void *p = memalign(alignment, size);
15,088,688✔
455
  if (NULL == p) {
15,084,085!
456
    if (ENOMEM == errno) {
×
457
      terrno = TSDB_CODE_OUT_OF_MEMORY;
×
458
    } else {
459
      terrno = TAOS_SYSTEM_ERROR(errno);
×
460
    }
461
  }
462
  return p;
15,084,085✔
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