- if set to 1, memory free operation does not call abort() for double
freeing a pointer or freeing an invalid address
- default is 0, can be set via config framework
... | ... |
@@ -398,6 +398,7 @@ SYN_BRANCH syn_branch |
398 | 398 |
MEMLOG "memlog"|"mem_log" |
399 | 399 |
MEMDBG "memdbg"|"mem_dbg" |
400 | 400 |
MEMSUM "mem_summary" |
401 |
+MEMSAFETY "mem_safety" |
|
401 | 402 |
CORELOG "corelog"|"core_log" |
402 | 403 |
SIP_WARNING sip_warning |
403 | 404 |
SERVER_SIGNATURE server_signature |
... | ... |
@@ -797,6 +798,7 @@ IMPORTFILE "import_file" |
797 | 798 |
<INITIAL>{MEMLOG} { count(); yylval.strval=yytext; return MEMLOG; } |
798 | 799 |
<INITIAL>{MEMDBG} { count(); yylval.strval=yytext; return MEMDBG; } |
799 | 800 |
<INITIAL>{MEMSUM} { count(); yylval.strval=yytext; return MEMSUM; } |
801 |
+<INITIAL>{MEMSAFETY} { count(); yylval.strval=yytext; return MEMSAFETY; } |
|
800 | 802 |
<INITIAL>{CORELOG} { count(); yylval.strval=yytext; return CORELOG; } |
801 | 803 |
<INITIAL>{SIP_WARNING} { count(); yylval.strval=yytext; return SIP_WARNING; } |
802 | 804 |
<INITIAL>{USER} { count(); yylval.strval=yytext; return USER; } |
... | ... |
@@ -452,6 +452,7 @@ extern char *finame; |
452 | 452 |
%token MEMLOG |
453 | 453 |
%token MEMDBG |
454 | 454 |
%token MEMSUM |
455 |
+%token MEMSAFETY |
|
455 | 456 |
%token CORELOG |
456 | 457 |
%token SIP_WARNING |
457 | 458 |
%token SERVER_SIGNATURE |
... | ... |
@@ -959,6 +960,8 @@ assign_stm: |
959 | 960 |
| MEMDBG EQUAL error { yyerror("int value expected"); } |
960 | 961 |
| MEMSUM EQUAL intno { default_core_cfg.mem_summary=$3; } |
961 | 962 |
| MEMSUM EQUAL error { yyerror("int value expected"); } |
963 |
+ | MEMSAFETY EQUAL intno { default_core_cfg.mem_safety=$3; } |
|
964 |
+ | MEMSAFETY EQUAL error { yyerror("int value expected"); } |
|
962 | 965 |
| CORELOG EQUAL intno { default_core_cfg.corelog=$3; } |
963 | 966 |
| CORELOG EQUAL error { yyerror("int value expected"); } |
964 | 967 |
| SIP_WARNING EQUAL NUMBER { sip_warning=$3; } |
... | ... |
@@ -121,6 +121,7 @@ struct cfg_group_core default_core_cfg = { |
121 | 121 |
L_DBG, /*!< memlog */ |
122 | 122 |
3, /*!< mem_summary -flags: 0 off, 1 pkg_status, 2 shm_status, |
123 | 123 |
4 pkg_sums, 8 shm_sums, 16 short_status */ |
124 |
+ 0, /*!< mem_safety - 0 disabled */ |
|
124 | 125 |
L_ERR, /*!< corelog */ |
125 | 126 |
L_ERR, /*!< latency log */ |
126 | 127 |
0, /*!< latency limit db */ |
... | ... |
@@ -312,6 +313,8 @@ cfg_def_t core_cfg_def[] = { |
312 | 313 |
" 4 - summary of pkg used blocks," |
313 | 314 |
" 8 - summary of shm used blocks," |
314 | 315 |
" 16 - short status instead of dump" }, |
316 |
+ {"mem_safety", CFG_VAR_INT|CFG_ATOMIC, 0, 0, 0, 0, |
|
317 |
+ "safety level for memory operations"}, |
|
315 | 318 |
{"corelog", CFG_VAR_INT|CFG_ATOMIC, 0, 0, 0, 0, |
316 | 319 |
"log level for non-critical core error messages"}, |
317 | 320 |
{"latency_log", CFG_VAR_INT|CFG_ATOMIC, 0, 0, 0, 0, |
... | ... |
@@ -108,6 +108,7 @@ struct cfg_group_core { |
108 | 108 |
int force_rport; /*!< if set rport will always be forced*/ |
109 | 109 |
int memlog; /*!< log level for memory status/summary info */ |
110 | 110 |
int mem_summary; /*!< display memory status/summary info on exit */ |
111 |
+ int mem_safety; /*!< memory safety control option */ |
|
111 | 112 |
int corelog; /*!< log level for non-critcal core error messages */ |
112 | 113 |
int latency_log; /*!< log level for latency limits messages */ |
113 | 114 |
int latency_limit_db; /*!< alert limit of running db commands */ |
... | ... |
@@ -436,9 +436,10 @@ void qm_free(struct qm_block* qm, void* p) |
436 | 436 |
#ifdef DBG_QM_MALLOC |
437 | 437 |
MDBG("qm_free(%p, %p), called from %s: %s(%d)\n", qm, p, file, func, line); |
438 | 438 |
if (p>(void*)qm->last_frag_end || p<(void*)qm->first_frag){ |
439 |
- LOG(L_CRIT, "BUG: qm_free: bad pointer %p (out of memory block!) - " |
|
440 |
- "aborting\n", p); |
|
441 |
- abort(); |
|
439 |
+ LOG(L_CRIT, "BUG: qm_free: bad pointer %p (out of memory block!)" |
|
440 |
+ " called from %s: %s(%d) - aborting\n", p, file, func, line); |
|
441 |
+ if(likely(cfg_get(core, core_cfg, mem_safety)==0)) |
|
442 |
+ abort(); |
|
442 | 443 |
} |
443 | 444 |
#endif |
444 | 445 |
if (p==0) { |
... | ... |
@@ -452,10 +453,11 @@ void qm_free(struct qm_block* qm, void* p) |
452 | 453 |
#ifdef DBG_QM_MALLOC |
453 | 454 |
qm_debug_frag(qm, f); |
454 | 455 |
if (f->u.is_free){ |
455 |
- LOG(L_CRIT, "BUG: qm_free: freeing already freed pointer," |
|
456 |
- " first free: %s: %s(%ld) - aborting\n", |
|
457 |
- f->file, f->func, f->line); |
|
458 |
- abort(); |
|
456 |
+ LOG(L_CRIT, "BUG: qm_free: freeing already freed pointer (%p)," |
|
457 |
+ " called from %s: %s(%d), first free %s: %s(%ld) - aborting\n", |
|
458 |
+ p, file, func, line, f->file, f->func, f->line); |
|
459 |
+ if(likely(cfg_get(core, core_cfg, mem_safety)==0)) |
|
460 |
+ abort(); |
|
459 | 461 |
} |
460 | 462 |
MDBG("qm_free: freeing frag. %p alloc'ed from %s: %s(%ld)\n", |
461 | 463 |
f, f->file, f->func, f->line); |
... | ... |
@@ -470,7 +472,7 @@ void qm_free(struct qm_block* qm, void* p) |
470 | 472 |
|
471 | 473 |
#ifdef QM_JOIN_FREE |
472 | 474 |
/* mark this fragment as used (might fall into the middle of joined frags) |
473 |
- to give us an extra change of detecting a double free call (if the joined |
|
475 |
+ to give us an extra chance of detecting a double free call (if the joined |
|
474 | 476 |
fragment has not yet been reused) */ |
475 | 477 |
f->u.nxt_free=(void*)0x1L; /* bogus value, just to mark it as free */ |
476 | 478 |
/* join packets if possible*/ |