diff options
| author | Martin Pitt <martin.pitt@ubuntu.com> | 2009-12-22 10:09:20 (GMT) |
|---|---|---|
| committer | Chris Coulson <chrisccoulson@googlemail.com> | 2009-12-23 15:51:11 (GMT) |
| commit | da66897950431870390f8dc3f798e24f23ffb8c8 (patch) | |
| tree | acdc2ae47e090f26c42b47ce75e0474cebccdc9b /glib/gtestutils.c | |
| parent | e9ab9eaff66b62c9653b90cca2eaf1d142f716a1 (diff) | |
| download | glib-da66897950431870390f8dc3f798e24f23ffb8c8.zip glib-da66897950431870390f8dc3f798e24f23ffb8c8.tar.xz | |
Support storing assertion messages into core dump
Crash interception/debugging systems like Apport or ABRT capture core dumps for
later crash analysis. However, if a program exits with an assertion failure,
the core dump is not useful since the assertion message is only printed to
stderr.
glibc recently got a patch which stores the message of assert() into the
__abort_msg global variable.
(http://sourceware.org/git/?p=glibc.git;a=commitdiff;h=48dcd0ba)
That works fine for programs which actually use the standard C assert() macro.
This patch adds the same functionality for glib's assertion tests. If we are
building against a glibc which already has __abort_msg (2.11 and later, or
backported above git commit), use that, otherwise put it into our own field
__glib_assert_msg.
Usage:
$ cat test.c
#include <glib.h>
int main() {
g_assert(1 < 0);
return 0;
}
$ ./test
**ERROR:test.c:5:main: assertion failed: (1 < 0)
Aborted (Core dumped)
$ gdb --batch --ex 'print (char*) __abort_msg' ./test core
[...]
$1 = 0x93bf028 "ERROR:test.c:5:main: assertion failed: (1 < 0)"
https://bugzilla.gnome.org/show_bug.cgi?id=594872
Diffstat (limited to 'glib/gtestutils.c')
| -rw-r--r-- | glib/gtestutils.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/glib/gtestutils.c b/glib/gtestutils.c index fdb9494..36a0a8e 100644 --- a/glib/gtestutils.c +++ b/glib/gtestutils.c @@ -40,6 +40,19 @@ #ifdef HAVE_SYS_SELECT_H #include <sys/select.h> #endif /* HAVE_SYS_SELECT_H */ + +/* if we have a recent enough glibc, use its __abort_msg variable for storing + * assertion messages (just like assert()). If not, declare our own variable, + * so that platforms with older glibc or different libc implementations can use + * this feature for debugging as well. + */ +#ifdef HAVE_LIBC_ABORT_MSG +extern char *__abort_msg; +#define ASSERT_MESSAGE_STORE __abort_msg +#else +char *__glib_assert_msg = NULL; +#define ASSERT_MESSAGE_STORE __glib_assert_msg +#endif /* --- structures --- */ struct GTestCase @@ -1297,6 +1310,16 @@ g_assertion_message (const char *domain, func, func[0] ? ":" : "", " ", message, NULL); g_printerr ("**\n%s\n", s); + + /* store assertion message in global variable, so that it can be found in a + * core dump; also, use standard C allocation here for compatiblity with + * glibc's __abort_msg variable */ + if (ASSERT_MESSAGE_STORE != NULL) + /* free the old one */ + free (ASSERT_MESSAGE_STORE); + ASSERT_MESSAGE_STORE = (char*) malloc (strlen (s) + 1); + strcpy (ASSERT_MESSAGE_STORE, s); + g_test_log (G_TEST_LOG_ERROR, s, NULL, 0, NULL); g_free (s); abort(); |