From 52d6233296ec84eb5b58fcbf7bc9da4b96a943aa Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 27 Jul 2012 17:40:29 -0700 Subject: [PATCH] Report errors to the log, not just stderr. In particular this affects assert(3) and __cxa_pure_virtual, both of which have managed to confuse people this week by apparently aborting without reason. (Because stderr goes nowhere, normally.) Bug: 6852995 Bug: 6840813 Change-Id: I7f5d17d5ddda439e217b7932096702dc013b9142 --- libc/bionic/stubs.c | 101 ++++++++++++------------ libc/private/bionic_atomic_inline.h | 8 +- libc/stdlib/assert.c | 32 ++++---- libc/unistd/abort.c | 7 +- libstdc++/Android.mk | 2 +- libstdc++/src/one_time_construction.cpp | 4 +- libstdc++/src/pure_virtual.cpp | 14 ++-- 7 files changed, 80 insertions(+), 88 deletions(-) diff --git a/libc/bionic/stubs.c b/libc/bionic/stubs.c index cc4c04ec3..1aeb58197 100644 --- a/libc/bionic/stubs.c +++ b/libc/bionic/stubs.c @@ -25,17 +25,19 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include + #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include static int do_getpw_r(int by_name, const char* name, uid_t uid, struct passwd* dst, char* buf, size_t byte_count, struct passwd** result) @@ -438,65 +440,62 @@ getgrnam(const char *name) return app_id_to_group( app_id_from_name(name), state ); } - -struct netent* getnetbyname(const char *name) -{ - fprintf(stderr, "FIX ME! implement getgrnam() %s:%d\n", __FILE__, __LINE__); - return NULL; +static void unimplemented_stub(const char* function) { + const char* fmt = "%s(3) is not implemented on Android\n"; + __libc_android_log_print(ANDROID_LOG_WARN, "libc", fmt, function); + fprintf(stderr, fmt, function); } -void endpwent(void) -{ +#define UNIMPLEMENTED unimplemented_stub(__PRETTY_FUNCTION__) + +struct netent* getnetbyname(const char* name) { + UNIMPLEMENTED; + return NULL; } -struct mntent* getmntent(FILE* f) -{ - fprintf(stderr, "FIX ME! implement getmntent() %s:%d\n", __FILE__, __LINE__); - return NULL; +void endpwent(void) { + UNIMPLEMENTED; } -char* ttyname(int fd) -{ - fprintf(stderr, "FIX ME! implement ttyname() %s:%d\n", __FILE__, __LINE__); - return NULL; +struct mntent* getmntent(FILE* f) { + UNIMPLEMENTED; + return NULL; } -int ttyname_r(int fd, char *buf, size_t buflen) -{ - fprintf(stderr, "FIX ME! implement ttyname_r() %s:%d\n", __FILE__, __LINE__); - return -ERANGE; +char* ttyname(int fd) { + UNIMPLEMENTED; + return NULL; } -struct netent *getnetbyaddr(uint32_t net, int type) -{ - fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); - return NULL; +int ttyname_r(int fd, char* buf, size_t buflen) { + UNIMPLEMENTED; + return -ERANGE; } -struct protoent *getprotobyname(const char *name) -{ - fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); - return NULL; +struct netent* getnetbyaddr(uint32_t net, int type) { + UNIMPLEMENTED; + return NULL; } -struct protoent *getprotobynumber(int proto) -{ - fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); - return NULL; +struct protoent* getprotobyname(const char* name) { + UNIMPLEMENTED; + return NULL; } -char* getusershell(void) -{ - fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); - return NULL; +struct protoent* getprotobynumber(int proto) { + UNIMPLEMENTED; + return NULL; } -void setusershell(void) -{ - fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); +char* getusershell(void) { + UNIMPLEMENTED; + return NULL; } -void endusershell(void) -{ - fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); +void setusershell(void) { + UNIMPLEMENTED; +} + +void endusershell(void) { + UNIMPLEMENTED; } diff --git a/libc/private/bionic_atomic_inline.h b/libc/private/bionic_atomic_inline.h index 0b348c3f1..6819af6b3 100644 --- a/libc/private/bionic_atomic_inline.h +++ b/libc/private/bionic_atomic_inline.h @@ -50,13 +50,13 @@ extern "C" { #define __ATOMIC_INLINE__ static __inline__ __attribute__((always_inline)) #ifdef __arm__ -# include +# include "bionic_atomic_arm.h" #elif defined(__i386__) -# include +# include "bionic_atomic_x86.h" #elif defined(__mips__) -# include +# include "bionic_atomic_mips.h" #else -# include +# include "bionic_atomic_gcc_builtin.h" #endif #define ANDROID_MEMBAR_FULL __bionic_memory_barrier diff --git a/libc/stdlib/assert.c b/libc/stdlib/assert.c index 816b050cf..7c0a86018 100644 --- a/libc/stdlib/assert.c +++ b/libc/stdlib/assert.c @@ -32,23 +32,23 @@ #include #include #include +#include -void -__assert(const char *file, int line, const char *failedexpr) -{ - (void)fprintf(stderr, - "assertion \"%s\" failed: file \"%s\", line %d\n", - failedexpr, file, line); - abort(); - /* NOTREACHED */ +// We log to stderr for the benefit of "adb shell" users, and the log for the benefit +// of regular app developers who want to see their asserts. + +void __assert(const char* file, int line, const char* failed_expression) { + const char* fmt = "%s:%d: assertion \"%s\" failed\n"; + __libc_android_log_print(ANDROID_LOG_FATAL, "libc", fmt, file, line, failed_expression); + fprintf(stderr, fmt, file, line, failed_expression); + abort(); + /* NOTREACHED */ } -void -__assert2(const char *file, int line, const char *func, const char *failedexpr) -{ - (void)fprintf(stderr, - "assertion \"%s\" failed: file \"%s\", line %d, function \"%s\"\n", - failedexpr, file, line, func); - abort(); - /* NOTREACHED */ +void __assert2(const char* file, int line, const char* function, const char* failed_expression) { + const char* fmt = "%s:%d: %s: assertion \"%s\" failed\n"; + __libc_android_log_print(ANDROID_LOG_FATAL, "libc", fmt, file, line, function, failed_expression); + fprintf(stderr, fmt, file, line, function, failed_expression); + abort(); + /* NOTREACHED */ } diff --git a/libc/unistd/abort.c b/libc/unistd/abort.c index 58d620d2f..4dffbae81 100644 --- a/libc/unistd/abort.c +++ b/libc/unistd/abort.c @@ -34,11 +34,6 @@ #include "thread_private.h" #include "atexit.h" -/* temporary, for bug hunting */ -#include "logd.h" -#define debug_log(format, ...) \ - __libc_android_log_print(ANDROID_LOG_DEBUG, "libc-abort", (format), ##__VA_ARGS__ ) - #ifdef __arm__ __LIBC_HIDDEN__ void __libc_android_abort(void) @@ -51,7 +46,7 @@ abort(void) static int cleanup_called = 0; sigset_t mask; - + sigfillset(&mask); /* * don't block SIGABRT to give any handler a chance; we ignore diff --git a/libstdc++/Android.mk b/libstdc++/Android.mk index 8bc181f55..7d27aa865 100644 --- a/libstdc++/Android.mk +++ b/libstdc++/Android.mk @@ -3,7 +3,7 @@ LOCAL_PATH:= $(call my-dir) # Common C++ flags to build this library. # Note that we need to access private Bionic headers # and define ANDROID_SMP accordingly. -libstdc++_cflags := -Ibionic/libc/private +libstdc++_cflags := -Ibionic/libc/ ifeq ($(TARGET_CPU_SMP),true) libstdc++_cflags += -DANDROID_SMP=1 else diff --git a/libstdc++/src/one_time_construction.cpp b/libstdc++/src/one_time_construction.cpp index 1eac3b1a5..3cfb2139f 100644 --- a/libstdc++/src/one_time_construction.cpp +++ b/libstdc++/src/one_time_construction.cpp @@ -11,8 +11,8 @@ #include #include #include -#include -#include +#include +#include // ARM C++ ABI and Itanium/x86 C++ ABI has different definition for // one time construction: diff --git a/libstdc++/src/pure_virtual.cpp b/libstdc++/src/pure_virtual.cpp index 663c1e996..affb80fcc 100644 --- a/libstdc++/src/pure_virtual.cpp +++ b/libstdc++/src/pure_virtual.cpp @@ -1,10 +1,8 @@ +#undef NDEBUG +#include -#include -#include - -extern "C" void __cxa_pure_virtual() -{ - fprintf(stderr, "Pure virtual function called. Are you calling virtual methods from a destructor?\n"); - abort(); +extern "C" void __cxa_pure_virtual() { + // We can't call __libc_android_log_write from libstdc++ because it's private, so cheat. + assert(!"Pure virtual function called. Are you calling virtual methods from a destructor?"); + /* NOTREACHED */ } -