atexit: clean up all the atexit code and fix the improper casts
authorAlan Cox <alan@linux.intel.com>
Wed, 21 Jan 2015 20:24:27 +0000 (20:24 +0000)
committerAlan Cox <alan@linux.intel.com>
Wed, 21 Jan 2015 20:24:27 +0000 (20:24 +0000)
Turns out atexit isn't a cc65 bug rather an interesting property of the
compiler.

cc65 requires the called function to unstack the arguments so that it can
fold together the argument popping and local recovery. This means that
calling a function declared as foo(void) cast as foo(int) doesn't work and
trashes your local variables.

A new to me and excitingly novel way of shooting yourself in the boot, but
perfectly valid compiler behaviour.

Library/include/stdlib.h
Library/libs/atexit.c
Library/libs/stdio0.c

index 75ab85f..1475175 100644 (file)
@@ -62,11 +62,8 @@ extern int putenv __P((char *));
 extern int setenv __P((char *, char *, int));
 extern void unsetenv __P((char *));
 
-typedef void (*atexit_t) __P((int));
-typedef void (*onexit_t) __P((int, void *));
+typedef void (*atexit_t) __P((void));
 extern int atexit __P((atexit_t));
-extern int on_exit __P((onexit_t, void *arg));
-extern onexit_t __cleanup;
 
 extern char *crypt __P((char *__key, char *__salt));
 
index 12914d1..8bd374e 100644 (file)
 #include <stdlib.h>
 #include <errno.h>
 
-/* ATEXIT.H */
-#define MAXONEXIT 10           /* AIUI Posix requires 10 */
+#define MAXATEXIT 10           /* AIUI Posix requires 10 */
 
-typedef void (*vfuncp) (int, void *);
+typedef void (*vfuncp) (void);
 
-extern struct exit_table {
-       onexit_t called;
-       void *argument;
-} __on_exit_table[MAXONEXIT];
+struct exit_table {
+       atexit_t called;
+} __atexit_table[MAXATEXIT];
 
-extern int __on_exit_count;
+extern int __atexit_count;
 
-/* End ATEXIT.H */
-int __on_exit_count = 0;
-struct exit_table __on_exit_table[MAXONEXIT];
+int __atexit_count = 0;
 
 void __do_exit(int rv)
 {
-       /* Static to work around a bug in cc65 */
-       static int count;
+       int count;
        vfuncp ptr;
 
-       count = __on_exit_count - 1;
-       __on_exit_count = -1;   /* ensure no more will be added */
+       count = __atexit_count - 1;
+       __atexit_count = -1;    /* ensure no more will be added */
 
        /* In reverse order */
        while (count >= 0) {
-               ptr = (vfuncp) __on_exit_table[count].called;
-               (*ptr) (rv, __on_exit_table[count].argument);
+               ptr = (vfuncp) __atexit_table[count].called;
+               (*ptr) ();
                --count;
        }
 }
 
-int on_exit(onexit_t ptr, void *arg)
+int atexit(atexit_t ptr)
 {
-       if (__on_exit_count < 0 || __on_exit_count >= MAXONEXIT) {
+       if (__atexit_count < 0 || __atexit_count >= MAXATEXIT) {
                errno = ENOMEM;
                return -1;
        }
        if (ptr) {
-               __on_exit_table[__on_exit_count].called = ptr;
-               __on_exit_table[__on_exit_count].argument = arg;
-               __on_exit_count++;
+               __atexit_table[__atexit_count].called = ptr;
+               __atexit_count++;
        }
        return 0;
 }
-
-int atexit(atexit_t ptr)
-{
-       return on_exit((onexit_t) ptr, 0);
-}
index cf4222c..5e025f0 100644 (file)
@@ -26,7 +26,7 @@ FILE stderr[1] = {
 
 /* Call the stdio initialiser; it's main job it to call atexit */
 
-STATIC void __stdio_close_all(VOID)
+STATIC void __stdio_close_all(void)
 {
        FILE *fp = __IO_list;