aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2016-03-13 20:23:41 -0500
committerRob Landley <rob@landley.net>2016-03-13 20:23:41 -0500
commiteb24df9749994d175a2de3b7fc0535abe46a7576 (patch)
tree73960237e28c3e222cbe054858641d7b4ece8a92 /lib
parent51d71f5c5b7040b50a38d9360561cee626eb2c2e (diff)
downloadtoybox-eb24df9749994d175a2de3b7fc0535abe46a7576.tar.gz
Split out _xexit() from xexit() and give sigatexit() multiple callbacks.
Diffstat (limited to 'lib')
-rw-r--r--lib/lib.c17
-rw-r--r--lib/lib.h1
-rw-r--r--lib/xwrap.c25
3 files changed, 38 insertions, 5 deletions
diff --git a/lib/lib.c b/lib/lib.c
index 1c1f2248..200f77d6 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -757,11 +757,24 @@ void generic_signal(int sig)
toys.signal = sig;
}
-// Install the same handler on every signal that defaults to killing the process
+void exit_signal(int sig)
+{
+ toys.exitval = sig|128;
+ xexit();
+}
+
+// Install the same handler on every signal that defaults to killing the
+// process, and
void sigatexit(void *handler)
{
+ struct arg_list *al = xmalloc(sizeof(struct arg_list));
int i;
- for (i=0; signames[i].num != SIGCHLD; i++) signal(signames[i].num, handler);
+
+ for (i=0; signames[i].num != SIGCHLD; i++)
+ signal(signames[i].num, exit_signal);
+ al->next = toys.xexit;
+ al->arg = handler;
+ toys.xexit = al;
}
// Convert name to signal number. If name == NULL print names.
diff --git a/lib/lib.h b/lib/lib.h
index 917be0c1..b12a110b 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -96,6 +96,7 @@ void show_help(FILE *out);
// xwrap.c
void xstrncpy(char *dest, char *src, size_t size);
void xstrncat(char *dest, char *src, size_t size);
+void _xexit(void) noreturn;
void xexit(void) noreturn;
void *xmalloc(size_t size);
void *xzalloc(size_t size);
diff --git a/lib/xwrap.c b/lib/xwrap.c
index 78103555..0b1ab8e9 100644
--- a/lib/xwrap.c
+++ b/lib/xwrap.c
@@ -28,13 +28,32 @@ void xstrncat(char *dest, char *src, size_t size)
strcpy(dest+len, src);
}
+// We replaced exit(), _exit(), and atexit() with xexit(), _xexit(), and
+// sigatexit(). This gives _xexit() the option to siglongjmp(toys.rebound, 1)
+// instead of exiting, lets xexit() report stdout flush failures to stderr
+// and change the exit code to indicate error, lets our toys.exit function
+// change happen for signal exit paths and lets us remove the functions
+// after we've called them.
+
+void _xexit(void)
+{
+ if (toys.rebound) siglongjmp(*toys.rebound, 1);
+
+ _exit(toys.exitval);
+}
+
void xexit(void)
{
- if (toys.rebound) longjmp(*toys.rebound, 1);
+ // Call toys.xexit functions in reverse order added.
+ while (toys.xexit) {
+ // This is typecasting xexit->arg to a function pointer,then calling it.
+ ((void (*)(void))(toys.xexit->arg))();
+
+ free(llist_pop(&toys.xexit));
+ }
if (fflush(NULL) || ferror(stdout))
if (!toys.exitval) perror_msg("write");
-
- exit(toys.exitval);
+ _xexit();
}
// Die unless we can allocate memory.