summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Sumrall <ksumrall@android.com>2011-03-23 22:08:53 -0700
committerKen Sumrall <ksumrall@android.com>2011-03-24 19:53:30 -0700
commit2ae7663e1e064000356ee9e49ebd08bdddc545f9 (patch)
tree038d0149c7d7f779da0487442bf3f4bf20c729b7
parent8c00dae657ce7941121ec218d07adeab9ee3d8a1 (diff)
downloadextras-2ae7663e1e064000356ee9e49ebd08bdddc545f9.tar.gz
Implement poor man's exception handling to prevent errors from killling recovery
make_ext4fs was originally designed to be a standalone program, and the error() macro calls exit() after printing a diagnostic. However, when it was turned into a library that recovery links against, calling exit() kills the entire recovery process, which the kernel starts back up, which dies, and the cycle continues. This changes make_ext4fs to use setjmp() early, and changes error to use longjmp to return to that point. When longjmp is called, the error handler just returns an error. If it was invoked as a standalone program, this causes the program to exit with an error. If it was invoked as a library function, the error return is gracefully handled by recovery. Change-Id: Iad50f46cac0ac399b5cdfd083d5712f88a10e48e
-rw-r--r--ext4_utils/ext4_utils.c2
-rw-r--r--ext4_utils/ext4_utils.h7
-rw-r--r--ext4_utils/make_ext4fs.c3
3 files changed, 10 insertions, 2 deletions
diff --git a/ext4_utils/ext4_utils.c b/ext4_utils/ext4_utils.c
index 211448c6..f4f04d90 100644
--- a/ext4_utils/ext4_utils.c
+++ b/ext4_utils/ext4_utils.c
@@ -42,6 +42,8 @@ int force = 0;
struct fs_info info;
struct fs_aux_info aux_info;
+jmp_buf setjmp_env;
+
/* returns 1 if a is a power of b */
static int is_power_of(int a, int b)
{
diff --git a/ext4_utils/ext4_utils.h b/ext4_utils/ext4_utils.h
index bed9933b..4518b98d 100644
--- a/ext4_utils/ext4_utils.h
+++ b/ext4_utils/ext4_utils.h
@@ -29,6 +29,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <setjmp.h>
#if defined(__APPLE__) && defined(__MACH__)
#define lseek64 lseek
@@ -49,9 +50,9 @@ static inline void *mmap64(void *addr, size_t length, int prot, int flags,
extern int force;
#define warn(fmt, args...) do { fprintf(stderr, "warning: %s: " fmt "\n", __func__, ## args); } while (0)
-#define error(fmt, args...) do { fprintf(stderr, "error: %s: " fmt "\n", __func__, ## args); if (!force) exit(EXIT_FAILURE); } while (0)
+#define error(fmt, args...) do { fprintf(stderr, "error: %s: " fmt "\n", __func__, ## args); if (!force) longjmp(setjmp_env, EXIT_FAILURE); } while (0)
#define error_errno(s, args...) error(s ": %s", ##args, strerror(errno))
-#define critical_error(fmt, args...) do { fprintf(stderr, "critical error: %s: " fmt "\n", __func__, ## args); exit(EXIT_FAILURE); } while (0)
+#define critical_error(fmt, args...) do { fprintf(stderr, "critical error: %s: " fmt "\n", __func__, ## args); longjmp(setjmp_env, EXIT_FAILURE); } while (0)
#define critical_error_errno(s, args...) critical_error(s ": %s", ##args, strerror(errno))
#define EXT4_SUPER_MAGIC 0xEF53
@@ -130,6 +131,8 @@ struct fs_aux_info {
extern struct fs_info info;
extern struct fs_aux_info aux_info;
+extern jmp_buf setjmp_env;
+
static inline int log_2(int j)
{
int i;
diff --git a/ext4_utils/make_ext4fs.c b/ext4_utils/make_ext4fs.c
index a87529df..c9fd9925 100644
--- a/ext4_utils/make_ext4fs.c
+++ b/ext4_utils/make_ext4fs.c
@@ -256,6 +256,9 @@ int make_ext4fs_internal(const char *filename, const char *directory,
u32 root_inode_num;
u16 root_mode;
+ if (setjmp(setjmp_env))
+ return EXIT_FAILURE; /* Handle a call to longjmp() */
+
if (info.len <= 0)
info.len = get_file_size(filename);