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>maint
							parent
							
								
									41ca19b6a6
								
							
						
					
					
						commit
						f8bb1d9431
					
				|  | @ -593,6 +593,7 @@ extern try_to_free_t set_try_to_free_routine(try_to_free_t); | ||||||
| extern char *xstrdup(const char *str); | extern char *xstrdup(const char *str); | ||||||
| extern void *xmalloc(size_t size); | extern void *xmalloc(size_t size); | ||||||
| extern void *xmallocz(size_t size); | extern void *xmallocz(size_t size); | ||||||
|  | extern void *xmallocz_gently(size_t size); | ||||||
| extern void *xmemdupz(const void *data, size_t len); | extern void *xmemdupz(const void *data, size_t len); | ||||||
| extern char *xstrndup(const char *str, size_t len); | extern char *xstrndup(const char *str, size_t len); | ||||||
| extern void *xrealloc(void *ptr, size_t size); | extern void *xrealloc(void *ptr, size_t size); | ||||||
|  |  | ||||||
							
								
								
									
										68
									
								
								wrapper.c
								
								
								
								
							
							
						
						
									
										68
									
								
								wrapper.c
								
								
								
								
							|  | @ -9,16 +9,23 @@ static void do_nothing(size_t size) | ||||||
|  |  | ||||||
| static void (*try_to_free_routine)(size_t size) = do_nothing; | static void (*try_to_free_routine)(size_t size) = do_nothing; | ||||||
|  |  | ||||||
| static void memory_limit_check(size_t size) | static int memory_limit_check(size_t size, int gentle) | ||||||
| { | { | ||||||
| 	static int limit = -1; | 	static int limit = -1; | ||||||
| 	if (limit == -1) { | 	if (limit == -1) { | ||||||
| 		const char *env = getenv("GIT_ALLOC_LIMIT"); | 		const char *env = getenv("GIT_ALLOC_LIMIT"); | ||||||
| 		limit = env ? atoi(env) * 1024 : 0; | 		limit = env ? atoi(env) * 1024 : 0; | ||||||
| 	} | 	} | ||||||
| 	if (limit && size > limit) | 	if (limit && size > limit) { | ||||||
| 		die("attempting to allocate %"PRIuMAX" over limit %d", | 		if (gentle) { | ||||||
| 		    (intmax_t)size, limit); | 			error("attempting to allocate %"PRIuMAX" over limit %d", | ||||||
|  | 			      (intmax_t)size, limit); | ||||||
|  | 			return -1; | ||||||
|  | 		} else | ||||||
|  | 			die("attempting to allocate %"PRIuMAX" over limit %d", | ||||||
|  | 			    (intmax_t)size, limit); | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| try_to_free_t set_try_to_free_routine(try_to_free_t routine) | try_to_free_t set_try_to_free_routine(try_to_free_t routine) | ||||||
|  | @ -42,11 +49,12 @@ char *xstrdup(const char *str) | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| void *xmalloc(size_t size) | static void *do_xmalloc(size_t size, int gentle) | ||||||
| { | { | ||||||
| 	void *ret; | 	void *ret; | ||||||
|  |  | ||||||
| 	memory_limit_check(size); | 	if (memory_limit_check(size, gentle)) | ||||||
|  | 		return NULL; | ||||||
| 	ret = malloc(size); | 	ret = malloc(size); | ||||||
| 	if (!ret && !size) | 	if (!ret && !size) | ||||||
| 		ret = malloc(1); | 		ret = malloc(1); | ||||||
|  | @ -55,9 +63,16 @@ void *xmalloc(size_t size) | ||||||
| 		ret = malloc(size); | 		ret = malloc(size); | ||||||
| 		if (!ret && !size) | 		if (!ret && !size) | ||||||
| 			ret = malloc(1); | 			ret = malloc(1); | ||||||
| 		if (!ret) | 		if (!ret) { | ||||||
| 			die("Out of memory, malloc failed (tried to allocate %lu bytes)", | 			if (!gentle) | ||||||
| 			    (unsigned long)size); | 				die("Out of memory, malloc failed (tried to allocate %lu bytes)", | ||||||
|  | 				    (unsigned long)size); | ||||||
|  | 			else { | ||||||
|  | 				error("Out of memory, malloc failed (tried to allocate %lu bytes)", | ||||||
|  | 				      (unsigned long)size); | ||||||
|  | 				return NULL; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| #ifdef XMALLOC_POISON | #ifdef XMALLOC_POISON | ||||||
| 	memset(ret, 0xA5, size); | 	memset(ret, 0xA5, size); | ||||||
|  | @ -65,16 +80,37 @@ void *xmalloc(size_t size) | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| void *xmallocz(size_t size) | void *xmalloc(size_t size) | ||||||
|  | { | ||||||
|  | 	return do_xmalloc(size, 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void *do_xmallocz(size_t size, int gentle) | ||||||
| { | { | ||||||
| 	void *ret; | 	void *ret; | ||||||
| 	if (unsigned_add_overflows(size, 1)) | 	if (unsigned_add_overflows(size, 1)) { | ||||||
| 		die("Data too large to fit into virtual memory space."); | 		if (gentle) { | ||||||
| 	ret = xmalloc(size + 1); | 			error("Data too large to fit into virtual memory space."); | ||||||
| 	((char*)ret)[size] = 0; | 			return NULL; | ||||||
|  | 		} else | ||||||
|  | 			die("Data too large to fit into virtual memory space."); | ||||||
|  | 	} | ||||||
|  | 	ret = do_xmalloc(size + 1, gentle); | ||||||
|  | 	if (ret) | ||||||
|  | 		((char*)ret)[size] = 0; | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void *xmallocz(size_t size) | ||||||
|  | { | ||||||
|  | 	return do_xmallocz(size, 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void *xmallocz_gently(size_t size) | ||||||
|  | { | ||||||
|  | 	return do_xmallocz(size, 1); | ||||||
|  | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of |  * xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of | ||||||
|  * "data" to the allocated memory, zero terminates the allocated memory, |  * "data" to the allocated memory, zero terminates the allocated memory, | ||||||
|  | @ -96,7 +132,7 @@ void *xrealloc(void *ptr, size_t size) | ||||||
| { | { | ||||||
| 	void *ret; | 	void *ret; | ||||||
|  |  | ||||||
| 	memory_limit_check(size); | 	memory_limit_check(size, 0); | ||||||
| 	ret = realloc(ptr, size); | 	ret = realloc(ptr, size); | ||||||
| 	if (!ret && !size) | 	if (!ret && !size) | ||||||
| 		ret = realloc(ptr, 1); | 		ret = realloc(ptr, 1); | ||||||
|  | @ -115,7 +151,7 @@ void *xcalloc(size_t nmemb, size_t size) | ||||||
| { | { | ||||||
| 	void *ret; | 	void *ret; | ||||||
|  |  | ||||||
| 	memory_limit_check(size * nmemb); | 	memory_limit_check(size * nmemb, 0); | ||||||
| 	ret = calloc(nmemb, size); | 	ret = calloc(nmemb, size); | ||||||
| 	if (!ret && (!nmemb || !size)) | 	if (!ret && (!nmemb || !size)) | ||||||
| 		ret = calloc(1, 1); | 		ret = calloc(1, 1); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Nguyễn Thái Ngọc Duy
						Nguyễn Thái Ngọc Duy