X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=glib%2Fgbacktrace.c;h=c59d18e1fdd192faaaac2b73827715b1981bceab;hb=7e3d32b7053b47ca7feecf185abac96b619770c2;hp=55457e2c1cd5112dca9b9343aa1e19261ec1b0c4;hpb=ca7dee5949185cd43a1f71c4e2b15987a0cc3160;p=platform%2Fupstream%2Fglib.git diff --git a/glib/gbacktrace.c b/glib/gbacktrace.c index 55457e2..c59d18e 100644 --- a/glib/gbacktrace.c +++ b/glib/gbacktrace.c @@ -12,9 +12,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library; if not, see . */ /* @@ -30,6 +28,7 @@ */ #include "config.h" +#include "glibconfig.h" #include #include @@ -39,30 +38,27 @@ #ifdef HAVE_SYS_TIME_H #include #endif -#ifdef HAVE_SYS_TIMES_H -#include -#endif #include -#ifdef HAVE_SYS_WAIT_H -#include -#endif #include -#ifdef HAVE_UNISTD_H -#include -#endif +#ifdef G_OS_UNIX +#include +#include #ifdef HAVE_SYS_SELECT_H #include #endif /* HAVE_SYS_SELECT_H */ +#endif -#include /* for bzero on BSD systems */ +#include #ifdef G_OS_WIN32 # define STRICT /* Strict typing, please */ # define _WIN32_WINDOWS 0x0401 /* to get IsDebuggerPresent */ # include # undef STRICT +#else +# include #endif #include "gbacktrace.h" @@ -70,6 +66,7 @@ #include "gtypes.h" #include "gmain.h" #include "gprintfint.h" +#include "gutils.h" #ifndef NO_FD_SET @@ -87,9 +84,60 @@ static void stack_trace (char **args); #endif -extern volatile gboolean glib_on_error_halt; +/* People want to hit this from their debugger... */ +GLIB_AVAILABLE_IN_ALL volatile gboolean glib_on_error_halt; volatile gboolean glib_on_error_halt = TRUE; +/** + * g_on_error_query: + * @prg_name: the program name, needed by gdb for the "[S]tack trace" + * option. If @prg_name is %NULL, g_get_prgname() is called to get + * the program name (which will work correctly if gdk_init() or + * gtk_init() has been called) + * + * Prompts the user with + * `[E]xit, [H]alt, show [S]tack trace or [P]roceed`. + * This function is intended to be used for debugging use only. + * The following example shows how it can be used together with + * the g_log() functions. + * + * |[ + * #include + * + * static void + * log_handler (const gchar *log_domain, + * GLogLevelFlags log_level, + * const gchar *message, + * gpointer user_data) + * { + * g_log_default_handler (log_domain, log_level, message, user_data); + * + * g_on_error_query (MY_PROGRAM_NAME); + * } + * + * int + * main (int argc, char *argv[]) + * { + * g_log_set_handler (MY_LOG_DOMAIN, + * G_LOG_LEVEL_WARNING | + * G_LOG_LEVEL_ERROR | + * G_LOG_LEVEL_CRITICAL, + * log_handler, + * NULL); + * ... + * ]| + * + * If "[E]xit" is selected, the application terminates with a call + * to _exit(0). + * + * If "[S]tack" trace is selected, g_on_error_stack_trace() is called. + * This invokes gdb, which attaches to the current process and shows + * a stack trace. The prompt is then shown again. + * + * If "[P]roceed" is selected, the function returns. + * + * This function may cause different actions on non-UNIX platforms. + */ void g_on_error_query (const gchar *prg_name) { @@ -159,10 +207,23 @@ g_on_error_query (const gchar *prg_name) #endif } +/** + * g_on_error_stack_trace: + * @prg_name: the program name, needed by gdb for the "[S]tack trace" + * option + * + * Invokes gdb, which attaches to the current process and shows a + * stack trace. Called by g_on_error_query() when the "[S]tack trace" + * option is selected. You can get the current process's program name + * with g_get_prgname(), assuming that you have called gtk_init() or + * gdk_init(). + * + * This function may cause different actions on non-UNIX platforms. + */ void g_on_error_stack_trace (const gchar *prg_name) { -#if defined(G_OS_UNIX) || defined(G_OS_BEOS) +#if defined(G_OS_UNIX) pid_t pid; gchar buf[16]; gchar *args[4] = { "gdb", NULL, NULL, NULL }; @@ -232,12 +293,19 @@ stack_trace (char **args) pid = fork (); if (pid == 0) { + /* Save stderr for printing failure below */ + int old_err = dup (2); + fcntl (old_err, F_SETFD, fcntl (old_err, F_GETFD) | FD_CLOEXEC); + close (0); dup (in_fd[0]); /* set the stdin to the in pipe */ close (1); dup (out_fd[1]); /* set the stdout to the out pipe */ close (2); dup (out_fd[1]); /* set the stderr to the out pipe */ execvp (args[0], args); /* exec gdb */ - perror ("exec failed"); + + /* Print failure to original stderr */ + close (2); dup (old_err); + perror ("exec gdb failed"); _exit (0); } else if (pid == (pid_t) -1)