2006-12-10 05:33:38 +08:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
1997-11-25 06:05:25 +08:00
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
2009-01-18 06:28:01 +08:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
1997-11-25 06:05:25 +08:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-18 06:28:01 +08:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
1997-11-25 06:05:25 +08:00
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2009-01-18 06:28:01 +08:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
2000-07-16 20:49:04 +08:00
|
|
|
|
1999-02-21 07:20:54 +08:00
|
|
|
#include "config.h"
|
|
|
|
|
2006-06-17 00:21:35 +08:00
|
|
|
#define _GNU_SOURCE /* need the POSIX signal API */
|
2006-05-30 09:55:42 +08:00
|
|
|
|
1999-02-21 07:20:54 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#ifdef HAVE_UNISTD_H
|
1997-11-25 06:05:25 +08:00
|
|
|
#include <unistd.h>
|
1999-02-21 07:20:54 +08:00
|
|
|
#endif
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2018-01-29 08:42:38 +08:00
|
|
|
#ifdef HAVE_EXECINFO_H
|
|
|
|
/* Allowing backtrace() API. */
|
|
|
|
#include <execinfo.h>
|
|
|
|
#endif
|
|
|
|
|
2013-10-15 07:58:39 +08:00
|
|
|
#include <gio/gio.h>
|
2000-07-16 20:49:04 +08:00
|
|
|
|
2004-01-24 01:24:44 +08:00
|
|
|
#include "libgimpbase/gimpbase.h"
|
2003-10-22 02:14:58 +08:00
|
|
|
|
2001-12-02 05:02:34 +08:00
|
|
|
#include "core/core-types.h"
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2001-12-02 05:02:34 +08:00
|
|
|
#include "core/gimp.h"
|
2001-08-07 08:06:06 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#include "errors.h"
|
1999-09-28 01:58:10 +08:00
|
|
|
|
1999-10-05 03:26:07 +08:00
|
|
|
#ifdef G_OS_WIN32
|
app/appenv.h New file. Includes <math.h>. Move G_PI, RINT(), ROUND() etc
1999-09-01 Tor Lillqvist <tml@iki.fi>
* app/appenv.h
* libgimp/gimpmath.h: New file. Includes <math.h>. Move G_PI,
RINT(), ROUND() etc from app/appenv.h here, so plug-ins can
use them, too. Remove some commented-out old stuff in appenv.h.
* libgimp/gimp.h: Include gimpmath.h.
* libgimp/gimp.c (gimp_main): Win32: Don't install signal
handlers, we can't do anything useful in the handler ourselves
anyway (it would be nice to print out a backtrace, but that seems
pretty hard to do, even if not impossible). Let Windows inform the
user about the crash. If the plug-in was compiled with MSVC, and
the user also has it, she is offered a chance to start the
debugger automatically anyway.
* app/*several*.c: Include gimpmath.h for G_PI etc. Don't include
<math.h>, as gimpmath.h includes it.
* plug-ins/*/*many*.c: Include config.h. Don't include <math.h>.
Remove all the duplicated definitions of G_PI and rint(). Use
RINT() instead of rint().
* app/app_procs.[ch]: app_exit() takes a gboolean.
* app/batch.c
* app/commands.c
* app/interface.c: Call app_exit() with FALSE or TRUE.
* app/main.c (on_error): Call gimp_fatal_error. (main): Don't
install any signal handler on Win32 here, either.
* app/errors.c (gimp_fatal_error, gimp_terminate): Win32: Format
the message and call MessageBox with it. g_on_error_query doesn't
do anything useful on Win32, and printf'ing a message to stdout or
stderr doesn't do anything, either, in a windowing application.
1999-09-02 04:30:56 +08:00
|
|
|
#include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
2018-01-23 10:38:46 +08:00
|
|
|
#define MAX_TRACES 3
|
2000-07-16 20:49:04 +08:00
|
|
|
|
2003-09-10 00:47:59 +08:00
|
|
|
/* private variables */
|
|
|
|
|
2006-09-10 01:31:28 +08:00
|
|
|
static Gimp *the_errors_gimp = NULL;
|
2003-09-10 00:47:59 +08:00
|
|
|
static gboolean use_debug_handler = FALSE;
|
|
|
|
static GimpStackTraceMode stack_trace_mode = GIMP_STACK_TRACE_QUERY;
|
|
|
|
static gchar *full_prog_name = NULL;
|
2018-01-27 04:20:52 +08:00
|
|
|
static gchar *backtrace_file = NULL;
|
2003-09-10 00:47:59 +08:00
|
|
|
|
2001-12-02 05:02:34 +08:00
|
|
|
|
|
|
|
/* local function prototypes */
|
|
|
|
|
2018-01-23 10:38:46 +08:00
|
|
|
static void gimp_third_party_message_log_func (const gchar *log_domain,
|
|
|
|
GLogLevelFlags flags,
|
|
|
|
const gchar *message,
|
|
|
|
gpointer data);
|
|
|
|
static void gimp_message_log_func (const gchar *log_domain,
|
|
|
|
GLogLevelFlags flags,
|
|
|
|
const gchar *message,
|
|
|
|
gpointer data);
|
|
|
|
static void gimp_error_log_func (const gchar *domain,
|
|
|
|
GLogLevelFlags flags,
|
|
|
|
const gchar *message,
|
|
|
|
gpointer data) G_GNUC_NORETURN;
|
2001-12-02 05:02:34 +08:00
|
|
|
|
2018-01-23 10:38:46 +08:00
|
|
|
static G_GNUC_NORETURN void gimp_eek (const gchar *reason,
|
|
|
|
const gchar *message,
|
|
|
|
gboolean use_handler);
|
2001-12-02 05:02:34 +08:00
|
|
|
|
2018-01-23 10:38:46 +08:00
|
|
|
static gchar * gimp_get_stack_trace (void);
|
2006-09-10 00:36:15 +08:00
|
|
|
|
|
|
|
|
2001-12-02 05:02:34 +08:00
|
|
|
/* public functions */
|
|
|
|
|
2003-09-10 00:47:59 +08:00
|
|
|
void
|
2006-09-10 01:31:28 +08:00
|
|
|
errors_init (Gimp *gimp,
|
|
|
|
const gchar *_full_prog_name,
|
|
|
|
gboolean _use_debug_handler,
|
2018-01-27 04:20:52 +08:00
|
|
|
GimpStackTraceMode _stack_trace_mode,
|
|
|
|
const gchar *_backtrace_file)
|
2003-09-10 00:47:59 +08:00
|
|
|
{
|
2006-09-10 01:31:28 +08:00
|
|
|
const gchar * const log_domains[] =
|
|
|
|
{
|
|
|
|
"Gimp",
|
|
|
|
"Gimp-Actions",
|
|
|
|
"Gimp-Base",
|
|
|
|
"Gimp-Composite",
|
|
|
|
"Gimp-Config",
|
|
|
|
"Gimp-Core",
|
|
|
|
"Gimp-Dialogs",
|
|
|
|
"Gimp-Display",
|
|
|
|
"Gimp-File",
|
2015-05-20 17:05:45 +08:00
|
|
|
"Gimp-GEGL",
|
2006-09-10 01:31:28 +08:00
|
|
|
"Gimp-GUI",
|
|
|
|
"Gimp-Menus",
|
2015-05-20 17:05:45 +08:00
|
|
|
"Gimp-Operations",
|
2006-09-10 01:31:28 +08:00
|
|
|
"Gimp-PDB",
|
|
|
|
"Gimp-Paint",
|
|
|
|
"Gimp-Paint-Funcs",
|
|
|
|
"Gimp-Plug-In",
|
|
|
|
"Gimp-Text",
|
|
|
|
"Gimp-Tools",
|
|
|
|
"Gimp-Vectors",
|
|
|
|
"Gimp-Widgets",
|
2015-05-20 17:05:45 +08:00
|
|
|
"Gimp-XCF",
|
|
|
|
"LibGimpBase",
|
|
|
|
"LibGimpColor",
|
|
|
|
"LibGimpConfig",
|
|
|
|
"LibGimpMath",
|
|
|
|
"LibGimpModule",
|
|
|
|
"LibGimpThumb",
|
|
|
|
"LibGimpWidgets"
|
2006-09-10 01:31:28 +08:00
|
|
|
};
|
|
|
|
gint i;
|
|
|
|
|
2006-09-10 00:36:15 +08:00
|
|
|
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
2003-09-10 00:47:59 +08:00
|
|
|
g_return_if_fail (_full_prog_name != NULL);
|
2003-10-24 18:19:33 +08:00
|
|
|
g_return_if_fail (full_prog_name == NULL);
|
2003-09-10 00:47:59 +08:00
|
|
|
|
2004-02-05 08:34:50 +08:00
|
|
|
#ifdef GIMP_UNSTABLE
|
2005-11-04 19:08:02 +08:00
|
|
|
g_printerr ("This is a development version of GIMP. "
|
2006-04-12 20:49:29 +08:00
|
|
|
"Debug messages may appear here.\n\n");
|
2004-02-05 08:34:50 +08:00
|
|
|
#endif /* GIMP_UNSTABLE */
|
2003-10-22 02:14:58 +08:00
|
|
|
|
2006-09-10 00:36:15 +08:00
|
|
|
the_errors_gimp = gimp;
|
2003-09-10 00:47:59 +08:00
|
|
|
use_debug_handler = _use_debug_handler ? TRUE : FALSE;
|
|
|
|
stack_trace_mode = _stack_trace_mode;
|
|
|
|
full_prog_name = g_strdup (_full_prog_name);
|
2018-01-27 04:20:52 +08:00
|
|
|
backtrace_file = g_strdup (_backtrace_file);
|
2003-05-29 19:34:30 +08:00
|
|
|
|
2006-09-10 01:31:28 +08:00
|
|
|
for (i = 0; i < G_N_ELEMENTS (log_domains); i++)
|
|
|
|
g_log_set_handler (log_domains[i],
|
2018-01-29 00:20:11 +08:00
|
|
|
#ifdef GIMP_UNSTABLE
|
|
|
|
G_LOG_LEVEL_WARNING |
|
|
|
|
#endif
|
2018-01-23 10:38:46 +08:00
|
|
|
G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_CRITICAL,
|
2006-09-10 19:39:24 +08:00
|
|
|
gimp_message_log_func, gimp);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2017-06-07 21:27:33 +08:00
|
|
|
g_log_set_handler ("GEGL",
|
|
|
|
G_LOG_LEVEL_MESSAGE,
|
|
|
|
gimp_third_party_message_log_func, gimp);
|
2006-09-10 01:31:28 +08:00
|
|
|
g_log_set_handler (NULL,
|
|
|
|
G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL,
|
2006-09-10 19:39:24 +08:00
|
|
|
gimp_error_log_func, gimp);
|
removed the gimp_busy boolean, check whether user_installation is needed
2001-07-10 Michael Natterer <mitch@gimp.org>
* app/app_procs.[ch]: removed the gimp_busy boolean, check whether
user_installation is needed here, not in user_install.c, parse
gtkrc an friends only if(!no_interface), create the Gimp object
before parsing gimp's rc files an pas it to the parse functions,
many other cleanups.
* app/appenums.h: added MessageHandlerType and StackTraceMode.
* app/appenv.h: removed MessageHandlerType, declare all global
variables from main.c (no more hidden global stuff please).
* app/errors.[ch]: added the fatal message func here (from main.c),
removed the StackTraceMode enum.
* app/gimprc.[ch]: renamed functions to gimprc_*(), pass a Gimp
pointer to some functions.
* app/gimpunit.c
* app/unitrc.h: ok, this is ugly: renamed all functions to
_gimp_unit_*() and made them public. The unit list is part
of the Gimp object now, so pass a Gimp* to all functions.
* app/libgimp_glue.[ch]: added EEKy wrappers for all gimp_unit_*()
functions which are used by widgets.
* app/main.c: cleaned up the global variables, removed the fatal
message handler, call app_init() directly, not via the
user_install stuff, misc. cleanups.
* app/user_install.[ch]: removed the check if user_installation is
needed (done by app_procs.c now).
* app/core/gimp.[ch]: added the user_unit list and the "busy"
boolean. Moved gimp_[set|unset]_busy() here. Added
gimp_initialize() which is called after unitrc and gimprc are
parsed.
* app/batch.c
* app/colormaps.c
* app/devices.c
* app/disp_callbacks.c
* app/gdisplay_ops.c
* app/gimphelp.c
* app/module_db.c
* app/nav_window.c
* app/plug_in.c
* app/core/gimpcontext.c
* app/core/gimpdatafiles.c
* app/core/gimpimage-convert.c
* app/core/gimpimage-duplicate.c
* app/core/gimpimage.c
* app/core/gimpparasite.c
* app/core/gimpparasitelist.h
* app/gui/file-open-dialog.c
* app/gui/gui.[ch]
* app/gui/info-dialog.c
* app/gui/info-window.c
* app/gui/preferences-dialog.c
* app/gui/session.c
* app/gui/tips-dialog.c
* app/gui/toolbox.c
* app/tools/gimpblendtool.c
* app/tools/gimpbucketfilltool.c
* app/tools/gimpcolorpickertool.c
* app/tools/gimpfuzzyselecttool.c
* app/tools/gimptransformtool.c
* app/tools/tool_manager.c
* app/widgets/gimpcolorpanel.c
* app/widgets/gimpcursor.c
* app/xcf/xcf-load.c
* app/xcf/xcf-save.c
* app/xcf/xcf.c
* tools/pdbgen/Makefile.am
* tools/pdbgen/app.pl
* tools/pdbgen/enums.pl
* tools/pdbgen/pdb/image.pdb
* tools/pdbgen/pdb/message.pdb
* tools/pdbgen/pdb/unit.pdb
* app/pdb/image_cmds.c
* app/pdb/message_cmds.c
* app/pdb/unit_cmds.c: changed accordingly, minor cleanups.
2001-07-11 03:16:16 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-06-13 17:27:32 +08:00
|
|
|
void
|
|
|
|
errors_exit (void)
|
|
|
|
{
|
|
|
|
the_errors_gimp = NULL;
|
2018-01-27 04:20:52 +08:00
|
|
|
|
|
|
|
if (backtrace_file)
|
|
|
|
g_free (backtrace_file);
|
2007-06-13 17:27:32 +08:00
|
|
|
}
|
|
|
|
|
removed the gimp_busy boolean, check whether user_installation is needed
2001-07-10 Michael Natterer <mitch@gimp.org>
* app/app_procs.[ch]: removed the gimp_busy boolean, check whether
user_installation is needed here, not in user_install.c, parse
gtkrc an friends only if(!no_interface), create the Gimp object
before parsing gimp's rc files an pas it to the parse functions,
many other cleanups.
* app/appenums.h: added MessageHandlerType and StackTraceMode.
* app/appenv.h: removed MessageHandlerType, declare all global
variables from main.c (no more hidden global stuff please).
* app/errors.[ch]: added the fatal message func here (from main.c),
removed the StackTraceMode enum.
* app/gimprc.[ch]: renamed functions to gimprc_*(), pass a Gimp
pointer to some functions.
* app/gimpunit.c
* app/unitrc.h: ok, this is ugly: renamed all functions to
_gimp_unit_*() and made them public. The unit list is part
of the Gimp object now, so pass a Gimp* to all functions.
* app/libgimp_glue.[ch]: added EEKy wrappers for all gimp_unit_*()
functions which are used by widgets.
* app/main.c: cleaned up the global variables, removed the fatal
message handler, call app_init() directly, not via the
user_install stuff, misc. cleanups.
* app/user_install.[ch]: removed the check if user_installation is
needed (done by app_procs.c now).
* app/core/gimp.[ch]: added the user_unit list and the "busy"
boolean. Moved gimp_[set|unset]_busy() here. Added
gimp_initialize() which is called after unitrc and gimprc are
parsed.
* app/batch.c
* app/colormaps.c
* app/devices.c
* app/disp_callbacks.c
* app/gdisplay_ops.c
* app/gimphelp.c
* app/module_db.c
* app/nav_window.c
* app/plug_in.c
* app/core/gimpcontext.c
* app/core/gimpdatafiles.c
* app/core/gimpimage-convert.c
* app/core/gimpimage-duplicate.c
* app/core/gimpimage.c
* app/core/gimpparasite.c
* app/core/gimpparasitelist.h
* app/gui/file-open-dialog.c
* app/gui/gui.[ch]
* app/gui/info-dialog.c
* app/gui/info-window.c
* app/gui/preferences-dialog.c
* app/gui/session.c
* app/gui/tips-dialog.c
* app/gui/toolbox.c
* app/tools/gimpblendtool.c
* app/tools/gimpbucketfilltool.c
* app/tools/gimpcolorpickertool.c
* app/tools/gimpfuzzyselecttool.c
* app/tools/gimptransformtool.c
* app/tools/tool_manager.c
* app/widgets/gimpcolorpanel.c
* app/widgets/gimpcursor.c
* app/xcf/xcf-load.c
* app/xcf/xcf-save.c
* app/xcf/xcf.c
* tools/pdbgen/Makefile.am
* tools/pdbgen/app.pl
* tools/pdbgen/enums.pl
* tools/pdbgen/pdb/image.pdb
* tools/pdbgen/pdb/message.pdb
* tools/pdbgen/pdb/unit.pdb
* app/pdb/image_cmds.c
* app/pdb/message_cmds.c
* app/pdb/unit_cmds.c: changed accordingly, minor cleanups.
2001-07-11 03:16:16 +08:00
|
|
|
void
|
2008-11-04 20:33:09 +08:00
|
|
|
gimp_fatal_error (const gchar *message)
|
removed the gimp_busy boolean, check whether user_installation is needed
2001-07-10 Michael Natterer <mitch@gimp.org>
* app/app_procs.[ch]: removed the gimp_busy boolean, check whether
user_installation is needed here, not in user_install.c, parse
gtkrc an friends only if(!no_interface), create the Gimp object
before parsing gimp's rc files an pas it to the parse functions,
many other cleanups.
* app/appenums.h: added MessageHandlerType and StackTraceMode.
* app/appenv.h: removed MessageHandlerType, declare all global
variables from main.c (no more hidden global stuff please).
* app/errors.[ch]: added the fatal message func here (from main.c),
removed the StackTraceMode enum.
* app/gimprc.[ch]: renamed functions to gimprc_*(), pass a Gimp
pointer to some functions.
* app/gimpunit.c
* app/unitrc.h: ok, this is ugly: renamed all functions to
_gimp_unit_*() and made them public. The unit list is part
of the Gimp object now, so pass a Gimp* to all functions.
* app/libgimp_glue.[ch]: added EEKy wrappers for all gimp_unit_*()
functions which are used by widgets.
* app/main.c: cleaned up the global variables, removed the fatal
message handler, call app_init() directly, not via the
user_install stuff, misc. cleanups.
* app/user_install.[ch]: removed the check if user_installation is
needed (done by app_procs.c now).
* app/core/gimp.[ch]: added the user_unit list and the "busy"
boolean. Moved gimp_[set|unset]_busy() here. Added
gimp_initialize() which is called after unitrc and gimprc are
parsed.
* app/batch.c
* app/colormaps.c
* app/devices.c
* app/disp_callbacks.c
* app/gdisplay_ops.c
* app/gimphelp.c
* app/module_db.c
* app/nav_window.c
* app/plug_in.c
* app/core/gimpcontext.c
* app/core/gimpdatafiles.c
* app/core/gimpimage-convert.c
* app/core/gimpimage-duplicate.c
* app/core/gimpimage.c
* app/core/gimpparasite.c
* app/core/gimpparasitelist.h
* app/gui/file-open-dialog.c
* app/gui/gui.[ch]
* app/gui/info-dialog.c
* app/gui/info-window.c
* app/gui/preferences-dialog.c
* app/gui/session.c
* app/gui/tips-dialog.c
* app/gui/toolbox.c
* app/tools/gimpblendtool.c
* app/tools/gimpbucketfilltool.c
* app/tools/gimpcolorpickertool.c
* app/tools/gimpfuzzyselecttool.c
* app/tools/gimptransformtool.c
* app/tools/tool_manager.c
* app/widgets/gimpcolorpanel.c
* app/widgets/gimpcursor.c
* app/xcf/xcf-load.c
* app/xcf/xcf-save.c
* app/xcf/xcf.c
* tools/pdbgen/Makefile.am
* tools/pdbgen/app.pl
* tools/pdbgen/enums.pl
* tools/pdbgen/pdb/image.pdb
* tools/pdbgen/pdb/message.pdb
* tools/pdbgen/pdb/unit.pdb
* app/pdb/image_cmds.c
* app/pdb/message_cmds.c
* app/pdb/unit_cmds.c: changed accordingly, minor cleanups.
2001-07-11 03:16:16 +08:00
|
|
|
{
|
2001-12-02 05:02:34 +08:00
|
|
|
gimp_eek ("fatal error", message, TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
1998-04-11 13:07:52 +08:00
|
|
|
|
|
|
|
void
|
2008-11-04 20:33:09 +08:00
|
|
|
gimp_terminate (const gchar *message)
|
1998-04-11 13:07:52 +08:00
|
|
|
{
|
2001-12-02 05:02:34 +08:00
|
|
|
gimp_eek ("terminated", message, use_debug_handler);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* private functions */
|
|
|
|
|
2017-06-07 21:27:33 +08:00
|
|
|
static void
|
|
|
|
gimp_third_party_message_log_func (const gchar *log_domain,
|
|
|
|
GLogLevelFlags flags,
|
|
|
|
const gchar *message,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
Gimp *gimp = data;
|
|
|
|
|
|
|
|
if (gimp)
|
|
|
|
{
|
|
|
|
/* Whereas all GIMP messages are processed under the same domain,
|
|
|
|
* we need to keep the log domain information for third party
|
|
|
|
* messages.
|
|
|
|
*/
|
|
|
|
gimp_show_message (gimp, NULL, GIMP_MESSAGE_WARNING,
|
2018-01-23 10:38:46 +08:00
|
|
|
log_domain, message, NULL);
|
2017-06-07 21:27:33 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_printerr ("%s: %s\n\n", log_domain, message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-10 01:31:28 +08:00
|
|
|
static void
|
|
|
|
gimp_message_log_func (const gchar *log_domain,
|
|
|
|
GLogLevelFlags flags,
|
|
|
|
const gchar *message,
|
|
|
|
gpointer data)
|
|
|
|
{
|
2018-01-23 10:38:46 +08:00
|
|
|
static gint n_traces;
|
|
|
|
GimpMessageSeverity severity = GIMP_MESSAGE_WARNING;
|
|
|
|
Gimp *gimp = data;
|
|
|
|
gchar *trace = NULL;
|
2018-01-26 08:55:54 +08:00
|
|
|
GimpCoreConfig *config = gimp->config;
|
|
|
|
gboolean generate_backtrace = FALSE;
|
2018-01-23 10:38:46 +08:00
|
|
|
|
2018-01-26 08:55:54 +08:00
|
|
|
g_object_get (G_OBJECT (config),
|
|
|
|
"generate-backtrace", &generate_backtrace,
|
|
|
|
NULL);
|
|
|
|
|
2018-01-29 00:20:11 +08:00
|
|
|
if (generate_backtrace &&
|
|
|
|
(flags & (G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING)))
|
2018-01-23 10:38:46 +08:00
|
|
|
{
|
2018-01-29 00:20:11 +08:00
|
|
|
severity = (flags & G_LOG_LEVEL_CRITICAL) ?
|
|
|
|
GIMP_MESSAGE_ERROR : GIMP_MESSAGE_WARNING;
|
2018-01-23 10:38:46 +08:00
|
|
|
|
|
|
|
if (n_traces < MAX_TRACES)
|
|
|
|
{
|
|
|
|
/* Getting debug traces is time-expensive, and worse, some
|
|
|
|
* critical errors have the bad habit to create more errors
|
|
|
|
* (the first ones are therefore usually the most useful).
|
|
|
|
* This is why we keep track of how many times we made traces
|
|
|
|
* and stop doing them after a while.
|
|
|
|
* Hence when this happens, critical errors are simply processed as
|
|
|
|
* lower level errors.
|
|
|
|
*/
|
|
|
|
trace = gimp_get_stack_trace ();
|
|
|
|
n_traces++;
|
|
|
|
}
|
|
|
|
}
|
2006-09-10 01:31:28 +08:00
|
|
|
|
2006-09-10 19:39:24 +08:00
|
|
|
if (gimp)
|
2006-09-10 01:31:28 +08:00
|
|
|
{
|
2018-01-23 10:38:46 +08:00
|
|
|
gimp_show_message (gimp, NULL, severity,
|
|
|
|
NULL, message, trace);
|
2006-09-10 01:31:28 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_printerr ("%s: %s\n\n",
|
|
|
|
gimp_filename_to_utf8 (full_prog_name), message);
|
2018-01-23 10:38:46 +08:00
|
|
|
if (trace)
|
|
|
|
g_printerr ("Back trace:\n%s\n\n", trace);
|
2006-09-10 01:31:28 +08:00
|
|
|
}
|
2018-01-23 10:38:46 +08:00
|
|
|
|
|
|
|
if (trace)
|
|
|
|
g_free (trace);
|
2006-09-10 01:31:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_error_log_func (const gchar *domain,
|
|
|
|
GLogLevelFlags flags,
|
|
|
|
const gchar *message,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
gimp_fatal_error (message);
|
|
|
|
}
|
|
|
|
|
2001-12-02 05:02:34 +08:00
|
|
|
static void
|
|
|
|
gimp_eek (const gchar *reason,
|
|
|
|
const gchar *message,
|
|
|
|
gboolean use_handler)
|
|
|
|
{
|
2018-01-27 06:47:11 +08:00
|
|
|
GimpCoreConfig *config = the_errors_gimp->config;
|
2018-01-26 08:55:54 +08:00
|
|
|
gboolean generate_backtrace = FALSE;
|
2018-01-27 06:47:11 +08:00
|
|
|
gboolean eek_handled = FALSE;
|
2018-01-26 08:55:54 +08:00
|
|
|
|
|
|
|
/* GIMP has 2 ways to handle termination signals and fatal errors: one
|
|
|
|
* is the stack trace mode which is set at start as command line
|
|
|
|
* option --stack-trace-mode, this won't change for the length of the
|
|
|
|
* session and outputs a trace in terminal; the other is set in
|
|
|
|
* preferences, outputs a trace in a GUI and can change anytime during
|
|
|
|
* the session.
|
|
|
|
* The GUI backtrace has priority if it is set.
|
|
|
|
*/
|
|
|
|
g_object_get (G_OBJECT (config),
|
|
|
|
"generate-backtrace", &generate_backtrace,
|
|
|
|
NULL);
|
|
|
|
|
2018-01-27 06:47:11 +08:00
|
|
|
/* Let's just always output on stdout at least so that there is a
|
|
|
|
* trace if the rest fails. */
|
2004-01-24 01:24:44 +08:00
|
|
|
g_printerr ("%s: %s: %s\n", gimp_filename_to_utf8 (full_prog_name),
|
|
|
|
reason, message);
|
removed the gimp_busy boolean, check whether user_installation is needed
2001-07-10 Michael Natterer <mitch@gimp.org>
* app/app_procs.[ch]: removed the gimp_busy boolean, check whether
user_installation is needed here, not in user_install.c, parse
gtkrc an friends only if(!no_interface), create the Gimp object
before parsing gimp's rc files an pas it to the parse functions,
many other cleanups.
* app/appenums.h: added MessageHandlerType and StackTraceMode.
* app/appenv.h: removed MessageHandlerType, declare all global
variables from main.c (no more hidden global stuff please).
* app/errors.[ch]: added the fatal message func here (from main.c),
removed the StackTraceMode enum.
* app/gimprc.[ch]: renamed functions to gimprc_*(), pass a Gimp
pointer to some functions.
* app/gimpunit.c
* app/unitrc.h: ok, this is ugly: renamed all functions to
_gimp_unit_*() and made them public. The unit list is part
of the Gimp object now, so pass a Gimp* to all functions.
* app/libgimp_glue.[ch]: added EEKy wrappers for all gimp_unit_*()
functions which are used by widgets.
* app/main.c: cleaned up the global variables, removed the fatal
message handler, call app_init() directly, not via the
user_install stuff, misc. cleanups.
* app/user_install.[ch]: removed the check if user_installation is
needed (done by app_procs.c now).
* app/core/gimp.[ch]: added the user_unit list and the "busy"
boolean. Moved gimp_[set|unset]_busy() here. Added
gimp_initialize() which is called after unitrc and gimprc are
parsed.
* app/batch.c
* app/colormaps.c
* app/devices.c
* app/disp_callbacks.c
* app/gdisplay_ops.c
* app/gimphelp.c
* app/module_db.c
* app/nav_window.c
* app/plug_in.c
* app/core/gimpcontext.c
* app/core/gimpdatafiles.c
* app/core/gimpimage-convert.c
* app/core/gimpimage-duplicate.c
* app/core/gimpimage.c
* app/core/gimpparasite.c
* app/core/gimpparasitelist.h
* app/gui/file-open-dialog.c
* app/gui/gui.[ch]
* app/gui/info-dialog.c
* app/gui/info-window.c
* app/gui/preferences-dialog.c
* app/gui/session.c
* app/gui/tips-dialog.c
* app/gui/toolbox.c
* app/tools/gimpblendtool.c
* app/tools/gimpbucketfilltool.c
* app/tools/gimpcolorpickertool.c
* app/tools/gimpfuzzyselecttool.c
* app/tools/gimptransformtool.c
* app/tools/tool_manager.c
* app/widgets/gimpcolorpanel.c
* app/widgets/gimpcursor.c
* app/xcf/xcf-load.c
* app/xcf/xcf-save.c
* app/xcf/xcf.c
* tools/pdbgen/Makefile.am
* tools/pdbgen/app.pl
* tools/pdbgen/enums.pl
* tools/pdbgen/pdb/image.pdb
* tools/pdbgen/pdb/message.pdb
* tools/pdbgen/pdb/unit.pdb
* app/pdb/image_cmds.c
* app/pdb/message_cmds.c
* app/pdb/unit_cmds.c: changed accordingly, minor cleanups.
2001-07-11 03:16:16 +08:00
|
|
|
|
2018-01-27 06:47:11 +08:00
|
|
|
#if ! defined (G_OS_WIN32) || defined (HAVE_EXCHNDL)
|
|
|
|
|
2001-12-02 05:02:34 +08:00
|
|
|
if (use_handler)
|
2000-05-11 05:21:23 +08:00
|
|
|
{
|
2018-01-26 09:17:13 +08:00
|
|
|
#ifndef GIMP_CONSOLE_COMPILATION
|
|
|
|
if (generate_backtrace && ! the_errors_gimp->no_interface)
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
2018-01-27 23:43:43 +08:00
|
|
|
/* If GUI backtrace enabled (it is disabled by default), it
|
2018-01-26 08:55:54 +08:00
|
|
|
* takes precedence over the command line argument.
|
|
|
|
*/
|
2018-01-27 23:43:43 +08:00
|
|
|
#ifdef G_OS_WIN32
|
2018-02-04 21:09:22 +08:00
|
|
|
const gchar *gimpdebug = "gimp-debug-tool-" GIMP_TOOL_VERSION ".exe";
|
2018-01-28 22:12:10 +08:00
|
|
|
#elif defined (PLATFORM_OSX)
|
2018-02-04 21:09:22 +08:00
|
|
|
const gchar *gimpdebug = "gimp-debug-tool-" GIMP_TOOL_VERSION;
|
2018-01-28 22:12:10 +08:00
|
|
|
#else
|
2018-02-04 21:09:22 +08:00
|
|
|
const gchar *gimpdebug = LIBEXECDIR "/gimp-debug-tool-" GIMP_TOOL_VERSION;
|
2018-01-27 23:43:43 +08:00
|
|
|
#endif
|
|
|
|
gchar *args[7] = { (gchar *) gimpdebug, full_prog_name, NULL,
|
2018-01-27 04:20:52 +08:00
|
|
|
(gchar *) reason, (gchar *) message,
|
|
|
|
backtrace_file, NULL };
|
2018-01-26 08:55:54 +08:00
|
|
|
gchar pid[16];
|
|
|
|
|
|
|
|
g_snprintf (pid, 16, "%u", (guint) getpid ());
|
|
|
|
args[2] = pid;
|
|
|
|
|
|
|
|
/* We don't care about any return value. If it fails, too
|
|
|
|
* bad, we just won't have any stack trace.
|
|
|
|
* We still need to use the sync() variant because we have
|
|
|
|
* to keep GIMP up long enough for the debugger to get its
|
|
|
|
* trace.
|
2018-01-25 21:32:39 +08:00
|
|
|
*/
|
2018-01-27 23:43:43 +08:00
|
|
|
#ifdef HAVE_EXCHNDL
|
|
|
|
/* On Win32, the trace has already been processed by ExcHnl
|
|
|
|
* and is waiting for us in a text file.
|
|
|
|
* We just want to spawn the trace GUI and exit GIMP directly.
|
|
|
|
*/
|
|
|
|
if (g_file_test (backtrace_file, G_FILE_TEST_IS_REGULAR) &&
|
|
|
|
g_spawn_async (NULL, args, NULL,
|
|
|
|
G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_STDOUT_TO_DEV_NULL,
|
|
|
|
NULL, NULL, NULL, NULL))
|
|
|
|
#else
|
|
|
|
/* On Unix machines, the spawned process will attach to the
|
|
|
|
* main GIMP process and will generate the backtrace. So we
|
|
|
|
* run it as a synced process.
|
|
|
|
*/
|
|
|
|
if (g_spawn_sync (NULL, args, NULL,
|
|
|
|
G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_STDOUT_TO_DEV_NULL,
|
|
|
|
NULL, NULL, NULL, NULL, NULL, NULL))
|
|
|
|
#endif
|
|
|
|
eek_handled = TRUE;
|
2018-01-26 08:55:54 +08:00
|
|
|
}
|
2018-01-27 06:47:11 +08:00
|
|
|
#endif /* !GIMP_CONSOLE_COMPILATION */
|
|
|
|
|
|
|
|
#ifndef G_OS_WIN32
|
|
|
|
if (! eek_handled)
|
2018-01-26 08:55:54 +08:00
|
|
|
{
|
|
|
|
switch (stack_trace_mode)
|
|
|
|
{
|
|
|
|
case GIMP_STACK_TRACE_NEVER:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_STACK_TRACE_QUERY:
|
|
|
|
{
|
|
|
|
sigset_t sigset;
|
|
|
|
|
|
|
|
sigemptyset (&sigset);
|
|
|
|
sigprocmask (SIG_SETMASK, &sigset, NULL);
|
|
|
|
|
|
|
|
if (the_errors_gimp)
|
|
|
|
gimp_gui_ungrab (the_errors_gimp);
|
|
|
|
|
|
|
|
g_on_error_query (full_prog_name);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_STACK_TRACE_ALWAYS:
|
|
|
|
{
|
|
|
|
sigset_t sigset;
|
|
|
|
|
|
|
|
sigemptyset (&sigset);
|
|
|
|
sigprocmask (SIG_SETMASK, &sigset, NULL);
|
|
|
|
|
|
|
|
g_on_error_stack_trace (full_prog_name);
|
|
|
|
}
|
|
|
|
break;
|
2006-04-12 20:49:29 +08:00
|
|
|
|
2018-01-26 08:55:54 +08:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2006-04-12 20:49:29 +08:00
|
|
|
}
|
2018-01-27 06:47:11 +08:00
|
|
|
#endif /* ! G_OS_WIN32 */
|
2000-05-11 05:21:23 +08:00
|
|
|
}
|
2018-01-27 06:47:11 +08:00
|
|
|
#endif /* ! G_OS_WIN32 || HAVE_EXCHNDL */
|
2000-07-16 20:49:04 +08:00
|
|
|
|
2018-01-27 06:47:11 +08:00
|
|
|
#if defined (G_OS_WIN32) && ! defined (GIMP_CONSOLE_COMPILATION)
|
2000-07-16 20:49:04 +08:00
|
|
|
/* g_on_error_* don't do anything reasonable on Win32. */
|
2018-01-27 06:47:11 +08:00
|
|
|
if (! eek_handled && ! the_errors_gimp->no_interface)
|
|
|
|
MessageBox (NULL, g_strdup_printf ("%s: %s", reason, message),
|
|
|
|
full_prog_name, MB_OK|MB_ICONERROR);
|
|
|
|
#endif
|
2000-07-16 20:49:04 +08:00
|
|
|
|
2003-10-10 18:02:34 +08:00
|
|
|
exit (EXIT_FAILURE);
|
1998-04-11 13:07:52 +08:00
|
|
|
}
|
2018-01-23 10:38:46 +08:00
|
|
|
|
|
|
|
static gchar *
|
|
|
|
gimp_get_stack_trace (void)
|
|
|
|
{
|
|
|
|
gchar *trace = NULL;
|
2018-01-26 09:17:13 +08:00
|
|
|
#ifndef G_OS_WIN32
|
2018-01-25 10:41:51 +08:00
|
|
|
gchar *args[7] = { "gdb", "-batch", "-ex", "backtrace full",
|
|
|
|
full_prog_name, NULL, NULL };
|
|
|
|
gchar *gdb_stdout;
|
|
|
|
gchar pid[16];
|
2018-01-23 10:38:46 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Though we should theoretically ask with GIMP_STACK_TRACE_QUERY, we
|
|
|
|
* just assume yes right now. TODO: improve this!
|
|
|
|
*/
|
|
|
|
if (stack_trace_mode == GIMP_STACK_TRACE_NEVER)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* This works only on UNIX systems. On Windows, we'll have to find
|
|
|
|
* another method, probably with DrMingW.
|
|
|
|
*/
|
2018-01-26 09:17:13 +08:00
|
|
|
#ifndef G_OS_WIN32
|
2018-01-25 10:41:51 +08:00
|
|
|
g_snprintf (pid, 16, "%u", (guint) getpid ());
|
|
|
|
args[5] = pid;
|
2018-01-23 10:38:46 +08:00
|
|
|
|
2018-01-25 10:41:51 +08:00
|
|
|
if (g_spawn_sync (NULL, args, NULL,
|
|
|
|
G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL,
|
|
|
|
NULL, NULL, &gdb_stdout, NULL, NULL, NULL))
|
2018-01-23 10:38:46 +08:00
|
|
|
{
|
2018-01-25 10:41:51 +08:00
|
|
|
trace = g_strdup (gdb_stdout);
|
2018-01-23 10:38:46 +08:00
|
|
|
}
|
2018-01-25 10:41:51 +08:00
|
|
|
else if (gdb_stdout)
|
2018-01-23 10:38:46 +08:00
|
|
|
{
|
2018-01-25 10:41:51 +08:00
|
|
|
g_free (gdb_stdout);
|
2018-01-23 10:38:46 +08:00
|
|
|
}
|
2018-01-27 01:12:56 +08:00
|
|
|
if (! trace)
|
|
|
|
{
|
|
|
|
/* Alternatively, use LLDB. It seems to be more common on some
|
|
|
|
* platforms, especially macOS.
|
|
|
|
*/
|
|
|
|
gchar *args_lldb[11] = { "lldb", "--attach-pid", NULL, "--batch",
|
|
|
|
"--one-line", "bt",
|
|
|
|
"--one-line-on-crash", "bt",
|
|
|
|
"--one-line-on-crash", "quit", NULL };
|
|
|
|
|
|
|
|
args_lldb[2] = pid;
|
|
|
|
if (g_spawn_sync (NULL, args_lldb, NULL,
|
|
|
|
G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL,
|
|
|
|
NULL, NULL, &gdb_stdout, NULL, NULL, NULL))
|
|
|
|
{
|
|
|
|
trace = g_strdup (gdb_stdout);
|
|
|
|
}
|
|
|
|
else if (gdb_stdout)
|
|
|
|
{
|
|
|
|
g_free (gdb_stdout);
|
|
|
|
}
|
|
|
|
}
|
2018-01-29 08:42:38 +08:00
|
|
|
#endif
|
2018-01-23 10:38:46 +08:00
|
|
|
|
2018-01-29 08:42:38 +08:00
|
|
|
#ifdef HAVE_EXECINFO_H
|
|
|
|
/* As a last resort, try using the backtrace() Linux API. It is a bit
|
|
|
|
* less fancy than gdb or lldb, which is why it is not given priority.
|
|
|
|
*/
|
|
|
|
if (! trace)
|
|
|
|
{
|
|
|
|
void *buffer[100];
|
|
|
|
char **symbols;
|
|
|
|
int n_symbols;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
n_symbols = backtrace (buffer, 100);
|
|
|
|
symbols = backtrace_symbols (buffer, n_symbols);
|
|
|
|
if (symbols)
|
|
|
|
{
|
|
|
|
GString *gtrace = g_string_new (NULL);
|
|
|
|
|
|
|
|
for (i = 0; i < n_symbols; i++)
|
|
|
|
{
|
|
|
|
g_string_append (gtrace,
|
|
|
|
(const gchar *) symbols[i]);
|
|
|
|
g_string_append_c (gtrace, '\n');
|
|
|
|
}
|
|
|
|
trace = g_string_free (gtrace, FALSE);
|
|
|
|
|
|
|
|
free (symbols);
|
|
|
|
}
|
|
|
|
}
|
2018-01-23 10:38:46 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return trace;
|
|
|
|
}
|