wrapper.c: introduce gentle xmallocz that does not die()

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Aug 16, 2014 at 10:08 UTC f8bb1d94311b7438e7e9831b51ffb047b7ae65d7
2 files changed +53 -16
git-compat-util.h
+1
@@ -593,6 +593,7 @@ extern try_to_free_t set_try_to_free_routine(try_to_free_t);
593 extern char *xstrdup(const char *str);
594 extern void *xmalloc(size_t size);
595 extern void *xmallocz(size_t size);
596 +extern void *xmallocz_gently(size_t size);
597 extern void *xmemdupz(const void *data, size_t len);
598 extern char *xstrndup(const char *str, size_t len);
599 extern void *xrealloc(void *ptr, size_t size);
wrapper.c
+52 -16
@@ -9,16 +9,23 @@ static void do_nothing(size_t size)
9
10 static void (*try_to_free_routine)(size_t size) = do_nothing;
11
12 -static void memory_limit_check(size_t size)
12 +static int memory_limit_check(size_t size, int gentle)
13 {
14 static int limit = -1;
15 if (limit == -1) {
16 const char *env = getenv("GIT_ALLOC_LIMIT");
17 limit = env ? atoi(env) * 1024 : 0;
18 }
19 - if (limit && size > limit)
20 - die("attempting to allocate %"PRIuMAX" over limit %d",
21 - (intmax_t)size, limit);
19 + if (limit && size > limit) {
20 + if (gentle) {
21 + error("attempting to allocate %"PRIuMAX" over limit %d",
22 + (intmax_t)size, limit);
23 + return -1;
24 + } else
25 + die("attempting to allocate %"PRIuMAX" over limit %d",
26 + (intmax_t)size, limit);
27 + }
28 + return 0;
29 }
30
31 try_to_free_t set_try_to_free_routine(try_to_free_t routine)
@@ -42,11 +49,12 @@ char *xstrdup(const char *str)
49 return ret;
50 }
51
45 -void *xmalloc(size_t size)
52 +static void *do_xmalloc(size_t size, int gentle)
53 {
54 void *ret;
55
49 - memory_limit_check(size);
56 + if (memory_limit_check(size, gentle))
57 + return NULL;
58 ret = malloc(size);
59 if (!ret && !size)
60 ret = malloc(1);
@@ -55,9 +63,16 @@ void *xmalloc(size_t size)
63 ret = malloc(size);
64 if (!ret && !size)
65 ret = malloc(1);
58 - if (!ret)
59 - die("Out of memory, malloc failed (tried to allocate %lu bytes)",
60 - (unsigned long)size);
66 + if (!ret) {
67 + if (!gentle)
68 + die("Out of memory, malloc failed (tried to allocate %lu bytes)",
69 + (unsigned long)size);
70 + else {
71 + error("Out of memory, malloc failed (tried to allocate %lu bytes)",
72 + (unsigned long)size);
73 + return NULL;
74 + }
75 + }
76 }
77 #ifdef XMALLOC_POISON
78 memset(ret, 0xA5, size);
@@ -65,16 +80,37 @@ void *xmalloc(size_t size)
80 return ret;
81 }
82
68 -void *xmallocz(size_t size)
83 +void *xmalloc(size_t size)
84 +{
85 + return do_xmalloc(size, 0);
86 +}
87 +
88 +static void *do_xmallocz(size_t size, int gentle)
89 {
90 void *ret;
71 - if (unsigned_add_overflows(size, 1))
72 - die("Data too large to fit into virtual memory space.");
73 - ret = xmalloc(size + 1);
74 - ((char*)ret)[size] = 0;
91 + if (unsigned_add_overflows(size, 1)) {
92 + if (gentle) {
93 + error("Data too large to fit into virtual memory space.");
94 + return NULL;
95 + } else
96 + die("Data too large to fit into virtual memory space.");
97 + }
98 + ret = do_xmalloc(size + 1, gentle);
99 + if (ret)
100 + ((char*)ret)[size] = 0;
101 return ret;
102 }
103
104 +void *xmallocz(size_t size)
105 +{
106 + return do_xmallocz(size, 0);
107 +}
108 +
109 +void *xmallocz_gently(size_t size)
110 +{
111 + return do_xmallocz(size, 1);
112 +}
113 +
114 /*
115 * xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of
116 * "data" to the allocated memory, zero terminates the allocated memory,
@@ -96,7 +132,7 @@ void *xrealloc(void *ptr, size_t size)
132 {
133 void *ret;
134
99 - memory_limit_check(size);
135 + memory_limit_check(size, 0);
136 ret = realloc(ptr, size);
137 if (!ret && !size)
138 ret = realloc(ptr, 1);
@@ -115,7 +151,7 @@ void *xcalloc(size_t nmemb, size_t size)
151 {
152 void *ret;
153
118 - memory_limit_check(size * nmemb);
154 + memory_limit_check(size * nmemb, 0);
155 ret = calloc(nmemb, size);
156 if (!ret && (!nmemb || !size))
157 ret = calloc(1, 1);