Clean up abort.

* A dlmalloc usage error shouldn't call abort(3) because we want to
  cause a SIGSEGV by writing the address dlmalloc didn't like to an
  address the kernel won't like, so that debuggerd will dump the
  memory around the address that upset dlmalloc.

* Switch to the simpler FreeBSD/NetBSD style of registering stdio
  cleanup. Hopefully this will let us simplify more of the stdio
  implementation.

* Clear the stdio cleanup handler before we abort because of a dlmalloc
  corruption error. This fixes the reported bug, where we'd hang inside
  dlmalloc because the stdio cleanup reentered dlmalloc.

Bug: 9301265
Change-Id: Ief31b389455d6876e5a68f0f5429567d37277dbc
diff --git a/libc/stdio/findfp.c b/libc/stdio/findfp.c
index 76ed5ee..863235b 100644
--- a/libc/stdio/findfp.c
+++ b/libc/stdio/findfp.c
@@ -171,10 +171,9 @@
 #endif
 
 /*
- * exit() and abort() call _cleanup() through the callback registered
- * with __atexit_register_cleanup(), set whenever we open or buffer a
- * file. This chicanery is done so that programs that do not use stdio
- * need not link it all in.
+ * exit() calls _cleanup() through *__cleanup, set whenever we
+ * open or buffer a file.  This chicanery is done so that programs
+ * that do not use stdio need not link it all in.
  *
  * The name `_cleanup' is, alas, fairly well known outside stdio.
  */
@@ -201,7 +200,7 @@
 		_FILEEXT_SETUP(usual+i, usualext+i);
 	}
 	/* make sure we clean up on exit */
-	__atexit_register_cleanup(_cleanup); /* conservative */
+	__cleanup = _cleanup; /* conservative */
 	__sdidinit = 1;
 out:
 	_THREAD_PRIVATE_MUTEX_UNLOCK(__sinit_mutex);
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index 664cec1..e3a40bc 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -58,7 +58,10 @@
 int	__sflags(const char *, int *);
 int	__vfprintf(FILE *, const char *, __va_list);
 
-extern void __atexit_register_cleanup(void (*)(void));
+/*
+ * Function to clean up streams, called from abort() and exit().
+ */
+extern void (*__cleanup)(void);
 extern int __sdidinit;
 
 /*
diff --git a/libc/stdio/makebuf.c b/libc/stdio/makebuf.c
index d47e27c..362cf05 100644
--- a/libc/stdio/makebuf.c
+++ b/libc/stdio/makebuf.c
@@ -65,7 +65,6 @@
 		fp->_bf._size = 1;
 		return;
 	}
-	__atexit_register_cleanup(_cleanup);
 	flags |= __SMBF;
 	fp->_bf._base = fp->_p = p;
 	fp->_bf._size = size;
diff --git a/libc/stdio/setvbuf.c b/libc/stdio/setvbuf.c
index 2fb76af..eb0ec68 100644
--- a/libc/stdio/setvbuf.c
+++ b/libc/stdio/setvbuf.c
@@ -124,8 +124,7 @@
 		flags |= __SNPT;
 
 	/*
-	 * Fix up the FILE fields, and set __cleanup for output flush on
-	 * exit (since we are buffered in some way).
+	 * Fix up the FILE fields.
 	 */
 	if (mode == _IOLBF)
 		flags |= __SLBF;
@@ -148,7 +147,6 @@
 		fp->_w = 0;
 	}
 	FUNLOCKFILE(fp);
-	__atexit_register_cleanup(_cleanup);
 
 	return (ret);
 }