1 // This module exists because there is code run by signal handlers that allocate memory. Most
2 // notably `job_waitsafe()`. They need to know if it is safe to do so. So we wrap the malloc family
3 // of functions.  See issue #563.
4 //
5 // TODO: Refactor those signal handlers so they only use async safe functions. Then remove this
6 // code.
7 //
8 #define NO_MALLOC_WRAPPERS 1
9 #include "config_ast.h"
10 
11 #include <stdbool.h>
12 
13 #if _hdr_stdlib
14 #include <stdlib.h>
15 #elif _hdr_malloc
16 #include <malloc.h>
17 #endif
18 
19 #include "ast_assert.h"
20 
21 volatile bool vmbusy_flag = false;
22 
ast_malloc(size_t size)23 void *ast_malloc(size_t size) {
24     vmbusy_flag = true;
25     void *p = malloc(size);
26     vmbusy_flag = false;
27     return p;
28 }
29 
ast_calloc(size_t count,size_t size)30 void *ast_calloc(size_t count, size_t size) {
31     vmbusy_flag = true;
32     void *p = calloc(count, size);
33     vmbusy_flag = false;
34     assert(p);
35     return p;
36 }
37 
ast_realloc(void * ptr,size_t size)38 void *ast_realloc(void *ptr, size_t size) {
39     vmbusy_flag = true;
40     void *p = realloc(ptr, size);
41     vmbusy_flag = false;
42     // On platforms like FreeBSD realloc with size == 0 frees the buffer and returns NULL. On other
43     // platforms a size of zero gets you a minimally sized block (typically four or eight bytes).
44     assert(!size || p);
45     return p;
46 }
47 
ast_free(void * ptr)48 void ast_free(void *ptr) {
49     vmbusy_flag = true;
50     free(ptr);
51     vmbusy_flag = false;
52 }
53