added hooks for running plug-ins under a memory debugger. Also, removed

2003-02-10  Manish Singh  <yosh@gimp.org>

        * app/plug-in/plug-in.[ch]: added hooks for running plug-ins under
        a memory debugger. Also, removed the args array from the PlugIn
        structure, replacing with simply a variable for the path to the
        plug-in (and one for a precalculated basename).

        * app/plug-in/plug-in-debug.[ch]: helper routines for the above

        * app/plug-in/plug-in-message.c
        * app/plug-in/plug-in-proc.c
        * app/plug-in/plug-in-progress.c: reflect new and renamed args members

        * app/plug-in/Makefile.am: added plug-in-debug.[ch]

        * app/core/core-types.h: added forward declaration for GimpPlugInDebug

        * app/core/gimp.[ch]: added structure member for GimpPlugInDebug

        * devel-docs/debug-plug-ins.txt: documented new feature
This commit is contained in:
Manish Singh 2003-02-11 01:21:21 +00:00 committed by Manish Singh
parent d55379066d
commit 96e7d31f58
22 changed files with 728 additions and 222 deletions

View File

@ -1,3 +1,24 @@
2003-02-10 Manish Singh <yosh@gimp.org>
* app/plug-in/plug-in.[ch]: added hooks for running plug-ins under
a memory debugger. Also, removed the args array from the PlugIn
structure, replacing with simply a variable for the path to the
plug-in (and one for a precalculated basename).
* app/plug-in/plug-in-debug.[ch]: helper routines for the above
* app/plug-in/plug-in-message.c
* app/plug-in/plug-in-proc.c
* app/plug-in/plug-in-progress.c: reflect new and renamed args members
* app/plug-in/Makefile.am: added plug-in-debug.[ch]
* app/core/core-types.h: added forward declaration for GimpPlugInDebug
* app/core/gimp.[ch]: added structure member for GimpPlugInDebug
* devel-docs/debug-plug-ins.txt: documented new feature
2003-02-10 Sven Neumann <sven@gimp.org>
* plug-ins/common/uniteditor.c: use the "cell-background-gdk"
@ -122,7 +143,7 @@
* libgimp/gimp.c: implemented plug-in debugging hooks. Also, use
G_LOG_DOMAIN instead of hardcoding "LibGimp" for g_log_set_handler.
* devel-docs/debug-plug-ins.txt: documenyed here
* devel-docs/debug-plug-ins.txt: documented here
* devel-docs/Makefile.am: add new file

View File

@ -169,6 +169,8 @@ typedef guint32 GimpTattoo;
typedef struct _GimpPaletteEntry GimpPaletteEntry;
typedef struct _GimpPlugInDebug GimpPlugInDebug;
/* EEK stuff */

View File

@ -200,7 +200,9 @@ gimp_init (Gimp *gimp)
gimp_modules_init (gimp);
gimp->environ_table = gimp_environ_table_new ();
gimp->environ_table = gimp_environ_table_new ();
gimp->plug_in_debug = NULL;
gimp->images = gimp_list_new (GIMP_TYPE_IMAGE,
GIMP_CONTAINER_POLICY_WEAK);

View File

@ -44,91 +44,93 @@ typedef struct _GimpClass GimpClass;
struct _Gimp
{
GimpObject parent_instance;
GimpObject parent_instance;
GimpCoreConfig *config;
GimpCoreConfig *edit_config; /* don't use this one, it's just
GimpCoreConfig *config;
GimpCoreConfig *edit_config; /* don't use this one, it's just
* for the preferences dialog
*/
gboolean be_verbose;
gboolean no_data;
gboolean no_interface;
gboolean use_shm;
GimpMessageHandlerType message_handler;
GimpStackTraceMode stack_trace_mode;
gboolean be_verbose;
gboolean no_data;
gboolean no_interface;
gboolean use_shm;
GimpMessageHandlerType message_handler;
GimpStackTraceMode stack_trace_mode;
GimpThreadFunc gui_threads_enter_func;
GimpThreadFunc gui_threads_leave_func;
GimpCreateDisplayFunc gui_create_display_func;
GimpSetBusyFunc gui_set_busy_func;
GimpUnsetBusyFunc gui_unset_busy_func;
GimpMessageFunc gui_message_func;
GimpThreadFunc gui_threads_enter_func;
GimpThreadFunc gui_threads_leave_func;
GimpCreateDisplayFunc gui_create_display_func;
GimpSetBusyFunc gui_set_busy_func;
GimpUnsetBusyFunc gui_unset_busy_func;
GimpMessageFunc gui_message_func;
gint busy;
guint busy_idle_id;
gint busy;
guint busy_idle_id;
GList *user_units;
gint n_user_units;
GList *user_units;
gint n_user_units;
GimpParasiteList *parasites;
GimpParasiteList *parasites;
GimpContainer *paint_info_list;
GimpContainer *paint_info_list;
GimpModuleDB *module_db;
gboolean write_modulerc;
GimpModuleDB *module_db;
gboolean write_modulerc;
GimpEnvironTable *environ_table;
GimpEnvironTable *environ_table;
GimpContainer *images;
gint next_image_ID;
guint32 next_guide_ID;
GHashTable *image_table;
GimpPlugInDebug *plug_in_debug;
gint next_item_ID;
GHashTable *item_table;
GimpContainer *images;
gint next_image_ID;
guint32 next_guide_ID;
GHashTable *image_table;
GimpContainer *displays;
gint next_display_ID;
gint next_item_ID;
GHashTable *item_table;
GimpBuffer *global_buffer;
GimpContainer *named_buffers;
GimpContainer *displays;
gint next_display_ID;
GimpDataFactory *brush_factory;
GimpDataFactory *pattern_factory;
GimpDataFactory *gradient_factory;
GimpDataFactory *palette_factory;
GimpBuffer *global_buffer;
GimpContainer *named_buffers;
GimpDataFactory *brush_factory;
GimpDataFactory *pattern_factory;
GimpDataFactory *gradient_factory;
GimpDataFactory *palette_factory;
GHashTable *procedural_ht;
GList *procedural_db_data_list;
GHashTable *procedural_ht;
GList *procedural_db_data_list;
GSList *load_procs;
GSList *save_procs;
GimpContainer *tool_info_list;
GimpToolInfo *standard_tool_info;
GSList *load_procs;
GSList *save_procs;
GimpContainer *tool_info_list;
GimpToolInfo *standard_tool_info;
/* the opened and saved images in MRU order */
GimpContainer *documents;
GimpContainer *documents;
/* image_new values */
GimpImageNewValues image_new_last_values;
gboolean have_current_cut_buffer;
GimpImageNewValues image_new_last_values;
gboolean have_current_cut_buffer;
/* the list of all contexts */
GList *context_list;
GList *context_list;
/* the hardcoded standard context */
GimpContext *standard_context;
GimpContext *standard_context;
/* the default context which is initialized from gimprc */
GimpContext *default_context;
GimpContext *default_context;
/* the context used by the interface */
GimpContext *user_context;
GimpContext *user_context;
/* the currently active context */
GimpContext *current_context;
GimpContext *current_context;
};
struct _GimpClass

View File

@ -96,7 +96,7 @@ plug_in_proc_def_get_progname (PlugInProcDef *proc_def)
return proc_def->prog;
case GIMP_TEMPORARY:
return ((PlugIn *) proc_def->db_info.exec_method.temporary.plug_in)->args[0];
return ((PlugIn *) proc_def->db_info.exec_method.temporary.plug_in)->prog;
default:
break;

View File

@ -19,6 +19,8 @@ libappplug_in_a_SOURCES = \
plug-in.h \
plug-ins.c \
plug-ins.h \
plug-in-debug.c \
plug-in-debug.h \
plug-in-def.c \
plug-in-def.h \
plug-in-message.c \

View File

@ -495,8 +495,8 @@ plug_in_handle_proc_install (PlugIn *plug_in,
g_message ("Plug-In \"%s\"\n(%s)\n"
"attempted to install procedure \"%s\"\n"
"which does not take the standard Plug-In args.",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0],
plug_in->name,
plug_in->prog,
proc_install->name);
return;
}
@ -511,8 +511,8 @@ plug_in_handle_proc_install (PlugIn *plug_in,
g_message ("Plug-In \"%s\"\n(%s)\n"
"attempted to install procedure \"%s\"\n"
"which does not take the standard Plug-In args.",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0],
plug_in->name,
plug_in->prog,
proc_install->name);
return;
}
@ -527,8 +527,8 @@ plug_in_handle_proc_install (PlugIn *plug_in,
g_message ("Plug-In \"%s\"\n(%s)\n"
"attempted to install procedure \"%s\"\n"
"which does not take the standard Plug-In args.",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0],
plug_in->name,
plug_in->prog,
proc_install->name);
return;
}
@ -545,8 +545,8 @@ plug_in_handle_proc_install (PlugIn *plug_in,
g_message ("Plug-In \"%s\"\n(%s)\n"
"attempted to install procedure \"%s\"\n"
"which does not take the standard Plug-In args.",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0],
plug_in->name,
plug_in->prog,
proc_install->name);
return;
}
@ -558,8 +558,8 @@ plug_in_handle_proc_install (PlugIn *plug_in,
"in an invalid menu location.\n"
"Use either \"<Toolbox>\", \"<Image>\", "
"\"<Load>\", or \"<Save>\".",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0],
plug_in->name,
plug_in->prog,
proc_install->name);
return;
}
@ -580,8 +580,8 @@ plug_in_handle_proc_install (PlugIn *plug_in,
"attempted to install procedure \"%s\"\n"
"which fails to comply with the array parameter\n"
"passing standard. Argument %d is noncompliant.",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0],
plug_in->name,
plug_in->prog,
proc_install->name, i);
return;
}
@ -626,8 +626,8 @@ plug_in_handle_proc_install (PlugIn *plug_in,
{
g_message ("Plug-In \"%s\"\n(%s)\n"
"attempted to install a procedure with invalid UTF-8 strings.\n",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0]);
plug_in->name,
plug_in->prog);
return;
}
@ -739,10 +739,10 @@ plug_in_handle_proc_install (PlugIn *plug_in,
plug_ins_temp_proc_def_add (plug_in->gimp, proc_def,
plug_ins_locale_domain (plug_in->gimp,
plug_in->args[0],
plug_in->prog,
NULL),
plug_ins_help_path (plug_in->gimp,
plug_in->args[0]));
plug_in->prog));
break;
}
}

View File

@ -54,7 +54,7 @@ plug_in_progress_start (PlugIn *plug_in,
g_return_if_fail (plug_in != NULL);
if (! message)
message = plug_in->args[0];
message = plug_in->prog;
if (gdisp_ID > 0)
gdisp = gimp_display_get_by_ID (plug_in->gimp, gdisp_ID);

View File

@ -95,6 +95,7 @@
#include "plug-in.h"
#include "plug-ins.h"
#include "plug-in-debug.h"
#include "plug-in-def.h"
#include "plug-in-message.h"
#include "plug-in-params.h"
@ -150,6 +151,8 @@ plug_in_init (Gimp *gimp)
*/
if (gimp->use_shm)
plug_in_shm_init (gimp);
plug_in_debug_init (gimp);
}
void
@ -159,6 +162,8 @@ plug_in_exit (Gimp *gimp)
g_return_if_fail (GIMP_IS_GIMP (gimp));
plug_in_debug_exit (gimp);
if (gimp->use_shm)
plug_in_shm_exit (gimp);
@ -257,14 +262,14 @@ plug_in_call_init (Gimp *gimp,
}
PlugIn *
plug_in_new (Gimp *gimp,
gchar *name)
plug_in_new (Gimp *gimp,
const gchar *prog)
{
PlugIn *plug_in;
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
g_return_val_if_fail (name != NULL, NULL);
g_return_val_if_fail (g_path_is_absolute (name), NULL);
g_return_val_if_fail (prog != NULL, NULL);
g_return_val_if_fail (g_path_is_absolute (prog), NULL);
plug_in = g_new0 (PlugIn, 1);
@ -281,13 +286,8 @@ plug_in_new (Gimp *gimp,
plug_in->starting_ext = FALSE;
plug_in->pid = 0;
plug_in->args[0] = g_strdup (name);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = NULL;
plug_in->args[3] = NULL;
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->name = g_path_get_basename (prog);
plug_in->prog = g_strdup (prog);
plug_in->my_read = NULL;
plug_in->my_write = NULL;
@ -329,18 +329,8 @@ plug_in_unref (PlugIn *plug_in)
if (plug_in->open)
plug_in_close (plug_in, TRUE);
if (plug_in->args[0])
g_free (plug_in->args[0]);
if (plug_in->args[1])
g_free (plug_in->args[1]);
if (plug_in->args[2])
g_free (plug_in->args[2]);
if (plug_in->args[3])
g_free (plug_in->args[3]);
if (plug_in->args[4])
g_free (plug_in->args[4]);
if (plug_in->args[5])
g_free (plug_in->args[5]);
g_free (plug_in->name);
g_free (plug_in->prog);
if (plug_in->progress)
plug_in_progress_end (plug_in);
@ -366,20 +356,29 @@ plug_in_prep_for_exec (gpointer data)
gboolean
plug_in_open (PlugIn *plug_in)
{
gint my_read[2];
gint my_write[2];
gchar **envp;
GError *error = NULL;
gint my_read[2];
gint my_write[2];
gchar **envp;
gchar *args[7], **argv, **debug_argv;
gchar *read_fd, *write_fd;
gchar *mode, *stm;
GError *error = NULL;
Gimp *gimp;
gboolean debug;
guint debug_flag;
guint spawn_flags;
g_return_val_if_fail (plug_in != NULL, FALSE);
gimp = plug_in->gimp;
/* Open two pipes. (Bidirectional communication).
*/
if ((pipe (my_read) == -1) || (pipe (my_write) == -1))
{
g_message ("pipe() failed: Unable to start Plug-In \"%s\"\n(%s)",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0]);
plug_in->name,
plug_in->prog);
return FALSE;
}
@ -413,9 +412,9 @@ plug_in_open (PlugIn *plug_in)
/* Remember the file descriptors for the pipes.
*/
plug_in->args[2] =
read_fd =
g_strdup_printf ("%d", g_io_channel_unix_get_fd (plug_in->his_read));
plug_in->args[3] =
write_fd =
g_strdup_printf ("%d", g_io_channel_unix_get_fd (plug_in->his_write));
/* Set the rest of the command line arguments.
@ -423,41 +422,67 @@ plug_in_open (PlugIn *plug_in)
*/
if (plug_in->query)
{
plug_in->args[4] = g_strdup ("-query");
mode = "-query";
debug_flag = GIMP_DEBUG_WRAP_QUERY;
}
else if (plug_in->init)
{
plug_in->args[4] = g_strdup ("-init");
mode = "-init";
debug_flag = GIMP_DEBUG_WRAP_INIT;
}
else
{
plug_in->args[4] = g_strdup ("-run");
mode = "-run";
debug_flag = GIMP_DEBUG_WRAP_RUN;
}
plug_in->args[5] = g_strdup_printf ("%d", plug_in->gimp->stack_trace_mode);
stm = g_strdup_printf ("%d", plug_in->gimp->stack_trace_mode);
#ifdef __EMX__
fcntl (my_read[0], F_SETFD, 1);
fcntl (my_write[1], F_SETFD, 1);
#endif
args[0] = plug_in->prog;
args[1] = "-gimp";
args[2] = read_fd;
args[3] = write_fd;
args[4] = mode;
args[5] = stm;
args[6] = NULL;
argv = args;
envp = gimp_environ_table_get_envp (plug_in->gimp->environ_table);
spawn_flags = G_SPAWN_LEAVE_DESCRIPTORS_OPEN | G_SPAWN_DO_NOT_REAP_CHILD;
debug = FALSE;
if (gimp->plug_in_debug)
{
debug_argv = plug_in_debug_argv (gimp, plug_in->name, debug_flag, args);
if (debug_argv)
{
debug = TRUE;
argv = debug_argv;
spawn_flags |= G_SPAWN_SEARCH_PATH;
}
}
/* Fork another process. We'll remember the process id so that we
* can later use it to kill the filter if necessary.
*/
envp = gimp_environ_table_get_envp (plug_in->gimp->environ_table);
if (! g_spawn_async (NULL, plug_in->args, envp,
G_SPAWN_LEAVE_DESCRIPTORS_OPEN |
G_SPAWN_DO_NOT_REAP_CHILD,
if (! g_spawn_async (NULL, argv, envp, spawn_flags,
plug_in_prep_for_exec, plug_in,
&plug_in->pid,
&error))
{
g_message ("Unable to run Plug-In: \"%s\"\n(%s)\n%s",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0],
plug_in->name,
plug_in->prog,
error->message);
g_error_free (error);
return FALSE;
goto cleanup;
}
g_io_channel_unref (plug_in->his_read);
@ -478,7 +503,17 @@ plug_in_open (PlugIn *plug_in)
}
plug_in->open = TRUE;
return TRUE;
cleanup:
if (debug)
g_free (argv);
g_free (read_fd);
g_free (write_fd);
g_free (stm);
return plug_in->open;
}
void
@ -541,7 +576,7 @@ plug_in_close (PlugIn *plug_in,
}
if (STILL_ACTIVE == dwExitCode)
{
g_warning ("Terminating %s ...", plug_in->args[0]);
g_warning ("Terminating %s ...", plug_in->prog);
TerminateProcess ((HANDLE) plug_in->pid, 0);
}
}
@ -662,8 +697,8 @@ plug_in_recv_message (GIOChannel *channel,
"The dying Plug-In may have messed up GIMP's internal state.\n"
"You may want to save your images and restart GIMP\n"
"to be on the safe side."),
g_path_get_basename (plug_in->args[0]),
plug_in->args[0]);
plug_in->name,
plug_in->prog);
if (! plug_in->open)
plug_in_unref (plug_in);

View File

@ -39,8 +39,10 @@ struct _PlugIn
guint recurse : 1; /* Do we have an own GMainLoop? */
guint in_temp_proc : 1; /* Is the plug-in busy with a temp proc? */
guint starting_ext : 1; /* Does the plug-in wait for extension_ack?*/
pid_t pid; /* Plug-ins process id */
gchar *args[7]; /* Plug-ins command line arguments */
pid_t pid; /* Plug-in's process id */
gchar *name; /* Plug-in's name */
gchar *prog; /* Plug-in's full path name */
GIOChannel *my_read; /* App's read and write channels */
GIOChannel *my_write;
@ -64,29 +66,29 @@ struct _PlugIn
};
void plug_in_init (Gimp *gimp);
void plug_in_exit (Gimp *gimp);
void plug_in_init (Gimp *gimp);
void plug_in_exit (Gimp *gimp);
void plug_in_call_query (Gimp *gimp,
PlugInDef *plug_in_def);
void plug_in_call_init (Gimp *gimp,
PlugInDef *plug_in_def);
void plug_in_call_query (Gimp *gimp,
PlugInDef *plug_in_def);
void plug_in_call_init (Gimp *gimp,
PlugInDef *plug_in_def);
PlugIn * plug_in_new (Gimp *gimp,
gchar *name);
PlugIn * plug_in_new (Gimp *gimp,
const gchar *prog);
void plug_in_ref (PlugIn *plug_in);
void plug_in_unref (PlugIn *plug_in);
void plug_in_ref (PlugIn *plug_in);
void plug_in_unref (PlugIn *plug_in);
gboolean plug_in_open (PlugIn *plug_in);
void plug_in_close (PlugIn *plug_in,
gboolean kill_it);
gboolean plug_in_open (PlugIn *plug_in);
void plug_in_close (PlugIn *plug_in,
gboolean kill_it);
void plug_in_push (PlugIn *plug_in);
void plug_in_push (PlugIn *plug_in);
void plug_in_pop (void);
void plug_in_main_loop (PlugIn *plug_in);
void plug_in_main_loop_quit (PlugIn *plug_in);
void plug_in_main_loop (PlugIn *plug_in);
void plug_in_main_loop_quit (PlugIn *plug_in);
extern PlugIn *current_plug_in;

View File

@ -0,0 +1,152 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <glib-object.h>
#include "core/core-types.h"
#include "core/gimp.h"
#include "plug-in-debug.h"
struct _GimpPlugInDebug
{
gchar *name;
guint flags;
gchar **args;
};
static const GDebugKey gimp_debug_wrap_keys[] = {
{"query", GIMP_DEBUG_WRAP_QUERY},
{"init", GIMP_DEBUG_WRAP_INIT},
{"run", GIMP_DEBUG_WRAP_RUN},
{"on", GIMP_DEBUG_WRAP_DEFAULT}
};
static const guint gimp_ndebug_wrap_keys = sizeof (gimp_debug_wrap_keys) / sizeof (GDebugKey);
void
plug_in_debug_init (Gimp *gimp)
{
GimpPlugInDebug *dbg;
const gchar *wrap, *wrapper;
gchar *debug_string;
gchar *name;
guint flags;
gchar **args;
GError *error = NULL;
g_return_if_fail (GIMP_IS_GIMP (gimp));
wrap = g_getenv ("GIMP_PLUGIN_DEBUG_WRAP");
wrapper = g_getenv ("GIMP_PLUGIN_DEBUG_WRAPPER");
if (!(wrap && wrapper))
return;
if (!g_shell_parse_argv (wrapper, NULL, &args, &error))
{
g_warning ("Unable to parse debug wrapper: \"%s\"\n%s",
wrapper, error->message);
g_error_free (error);
return;
}
dbg = g_new (GimpPlugInDebug, 1);
dbg->args = args;
debug_string = strchr (wrap, ',');
if (debug_string)
{
dbg->name = g_strndup (wrap, debug_string - wrap);
dbg->flags = g_parse_debug_string (debug_string + 1,
gimp_debug_wrap_keys,
gimp_ndebug_wrap_keys);
}
else
{
dbg->name = g_strdup (wrap);
dbg->flags = GIMP_DEBUG_WRAP_DEFAULT;
}
gimp->plug_in_debug = dbg;
}
void
plug_in_debug_exit (Gimp *gimp)
{
GimpPlugInDebug *dbg;
g_return_if_fail (GIMP_IS_GIMP (gimp));
dbg = gimp->plug_in_debug;
if (dbg == NULL)
return;
if (dbg->name)
g_free (dbg->name);
if (dbg->args)
g_strfreev (dbg->args);
g_free (dbg);
gimp->plug_in_debug = NULL;
}
gchar **
plug_in_debug_argv (Gimp *gimp,
const gchar *name,
GimpDebugWrapFlag flag,
gchar **args)
{
GimpPlugInDebug *dbg;
GPtrArray *argv;
gchar **arg;
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
g_return_val_if_fail (gimp->plug_in_debug != NULL, NULL);
g_return_val_if_fail (args != NULL, NULL);
dbg = gimp->plug_in_debug;
if (!(dbg->flags & flag) || (strcmp (dbg->name, name) != 0))
return NULL;
argv = g_ptr_array_sized_new (8);
for (arg = gimp->plug_in_debug->args; *arg != NULL; arg++)
g_ptr_array_add (argv, *arg);
for (arg = args; *arg != NULL; arg++)
g_ptr_array_add (argv, *arg);
g_ptr_array_add (argv, NULL);
return (gchar **) g_ptr_array_free (argv, FALSE);
}

View File

@ -0,0 +1,42 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __PLUG_IN_DEBUG_H__
#define __PLUG_IN_DEBUG_H__
typedef enum
{
GIMP_DEBUG_WRAP_QUERY = 1 << 0,
GIMP_DEBUG_WRAP_INIT = 1 << 1,
GIMP_DEBUG_WRAP_RUN = 1 << 2,
GIMP_DEBUG_WRAP_DEFAULT = GIMP_DEBUG_WRAP_RUN
} GimpDebugWrapFlag;
void plug_in_debug_init (Gimp *gimp);
void plug_in_debug_exit (Gimp *gimp);
gchar **plug_in_debug_argv (Gimp *gimp,
const gchar *name,
GimpDebugWrapFlag flag,
gchar **args);
#endif /* __PLUG_IN_DEBUG_H__ */

View File

@ -96,7 +96,7 @@ plug_in_proc_def_get_progname (PlugInProcDef *proc_def)
return proc_def->prog;
case GIMP_TEMPORARY:
return ((PlugIn *) proc_def->db_info.exec_method.temporary.plug_in)->args[0];
return ((PlugIn *) proc_def->db_info.exec_method.temporary.plug_in)->prog;
default:
break;

152
app/plug-in/plug-in-debug.c Normal file
View File

@ -0,0 +1,152 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <glib-object.h>
#include "core/core-types.h"
#include "core/gimp.h"
#include "plug-in-debug.h"
struct _GimpPlugInDebug
{
gchar *name;
guint flags;
gchar **args;
};
static const GDebugKey gimp_debug_wrap_keys[] = {
{"query", GIMP_DEBUG_WRAP_QUERY},
{"init", GIMP_DEBUG_WRAP_INIT},
{"run", GIMP_DEBUG_WRAP_RUN},
{"on", GIMP_DEBUG_WRAP_DEFAULT}
};
static const guint gimp_ndebug_wrap_keys = sizeof (gimp_debug_wrap_keys) / sizeof (GDebugKey);
void
plug_in_debug_init (Gimp *gimp)
{
GimpPlugInDebug *dbg;
const gchar *wrap, *wrapper;
gchar *debug_string;
gchar *name;
guint flags;
gchar **args;
GError *error = NULL;
g_return_if_fail (GIMP_IS_GIMP (gimp));
wrap = g_getenv ("GIMP_PLUGIN_DEBUG_WRAP");
wrapper = g_getenv ("GIMP_PLUGIN_DEBUG_WRAPPER");
if (!(wrap && wrapper))
return;
if (!g_shell_parse_argv (wrapper, NULL, &args, &error))
{
g_warning ("Unable to parse debug wrapper: \"%s\"\n%s",
wrapper, error->message);
g_error_free (error);
return;
}
dbg = g_new (GimpPlugInDebug, 1);
dbg->args = args;
debug_string = strchr (wrap, ',');
if (debug_string)
{
dbg->name = g_strndup (wrap, debug_string - wrap);
dbg->flags = g_parse_debug_string (debug_string + 1,
gimp_debug_wrap_keys,
gimp_ndebug_wrap_keys);
}
else
{
dbg->name = g_strdup (wrap);
dbg->flags = GIMP_DEBUG_WRAP_DEFAULT;
}
gimp->plug_in_debug = dbg;
}
void
plug_in_debug_exit (Gimp *gimp)
{
GimpPlugInDebug *dbg;
g_return_if_fail (GIMP_IS_GIMP (gimp));
dbg = gimp->plug_in_debug;
if (dbg == NULL)
return;
if (dbg->name)
g_free (dbg->name);
if (dbg->args)
g_strfreev (dbg->args);
g_free (dbg);
gimp->plug_in_debug = NULL;
}
gchar **
plug_in_debug_argv (Gimp *gimp,
const gchar *name,
GimpDebugWrapFlag flag,
gchar **args)
{
GimpPlugInDebug *dbg;
GPtrArray *argv;
gchar **arg;
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
g_return_val_if_fail (gimp->plug_in_debug != NULL, NULL);
g_return_val_if_fail (args != NULL, NULL);
dbg = gimp->plug_in_debug;
if (!(dbg->flags & flag) || (strcmp (dbg->name, name) != 0))
return NULL;
argv = g_ptr_array_sized_new (8);
for (arg = gimp->plug_in_debug->args; *arg != NULL; arg++)
g_ptr_array_add (argv, *arg);
for (arg = args; *arg != NULL; arg++)
g_ptr_array_add (argv, *arg);
g_ptr_array_add (argv, NULL);
return (gchar **) g_ptr_array_free (argv, FALSE);
}

View File

@ -0,0 +1,42 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __PLUG_IN_DEBUG_H__
#define __PLUG_IN_DEBUG_H__
typedef enum
{
GIMP_DEBUG_WRAP_QUERY = 1 << 0,
GIMP_DEBUG_WRAP_INIT = 1 << 1,
GIMP_DEBUG_WRAP_RUN = 1 << 2,
GIMP_DEBUG_WRAP_DEFAULT = GIMP_DEBUG_WRAP_RUN
} GimpDebugWrapFlag;
void plug_in_debug_init (Gimp *gimp);
void plug_in_debug_exit (Gimp *gimp);
gchar **plug_in_debug_argv (Gimp *gimp,
const gchar *name,
GimpDebugWrapFlag flag,
gchar **args);
#endif /* __PLUG_IN_DEBUG_H__ */

View File

@ -495,8 +495,8 @@ plug_in_handle_proc_install (PlugIn *plug_in,
g_message ("Plug-In \"%s\"\n(%s)\n"
"attempted to install procedure \"%s\"\n"
"which does not take the standard Plug-In args.",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0],
plug_in->name,
plug_in->prog,
proc_install->name);
return;
}
@ -511,8 +511,8 @@ plug_in_handle_proc_install (PlugIn *plug_in,
g_message ("Plug-In \"%s\"\n(%s)\n"
"attempted to install procedure \"%s\"\n"
"which does not take the standard Plug-In args.",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0],
plug_in->name,
plug_in->prog,
proc_install->name);
return;
}
@ -527,8 +527,8 @@ plug_in_handle_proc_install (PlugIn *plug_in,
g_message ("Plug-In \"%s\"\n(%s)\n"
"attempted to install procedure \"%s\"\n"
"which does not take the standard Plug-In args.",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0],
plug_in->name,
plug_in->prog,
proc_install->name);
return;
}
@ -545,8 +545,8 @@ plug_in_handle_proc_install (PlugIn *plug_in,
g_message ("Plug-In \"%s\"\n(%s)\n"
"attempted to install procedure \"%s\"\n"
"which does not take the standard Plug-In args.",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0],
plug_in->name,
plug_in->prog,
proc_install->name);
return;
}
@ -558,8 +558,8 @@ plug_in_handle_proc_install (PlugIn *plug_in,
"in an invalid menu location.\n"
"Use either \"<Toolbox>\", \"<Image>\", "
"\"<Load>\", or \"<Save>\".",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0],
plug_in->name,
plug_in->prog,
proc_install->name);
return;
}
@ -580,8 +580,8 @@ plug_in_handle_proc_install (PlugIn *plug_in,
"attempted to install procedure \"%s\"\n"
"which fails to comply with the array parameter\n"
"passing standard. Argument %d is noncompliant.",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0],
plug_in->name,
plug_in->prog,
proc_install->name, i);
return;
}
@ -626,8 +626,8 @@ plug_in_handle_proc_install (PlugIn *plug_in,
{
g_message ("Plug-In \"%s\"\n(%s)\n"
"attempted to install a procedure with invalid UTF-8 strings.\n",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0]);
plug_in->name,
plug_in->prog);
return;
}
@ -739,10 +739,10 @@ plug_in_handle_proc_install (PlugIn *plug_in,
plug_ins_temp_proc_def_add (plug_in->gimp, proc_def,
plug_ins_locale_domain (plug_in->gimp,
plug_in->args[0],
plug_in->prog,
NULL),
plug_ins_help_path (plug_in->gimp,
plug_in->args[0]));
plug_in->prog));
break;
}
}

View File

@ -96,7 +96,7 @@ plug_in_proc_def_get_progname (PlugInProcDef *proc_def)
return proc_def->prog;
case GIMP_TEMPORARY:
return ((PlugIn *) proc_def->db_info.exec_method.temporary.plug_in)->args[0];
return ((PlugIn *) proc_def->db_info.exec_method.temporary.plug_in)->prog;
default:
break;

View File

@ -96,7 +96,7 @@ plug_in_proc_def_get_progname (PlugInProcDef *proc_def)
return proc_def->prog;
case GIMP_TEMPORARY:
return ((PlugIn *) proc_def->db_info.exec_method.temporary.plug_in)->args[0];
return ((PlugIn *) proc_def->db_info.exec_method.temporary.plug_in)->prog;
default:
break;

View File

@ -54,7 +54,7 @@ plug_in_progress_start (PlugIn *plug_in,
g_return_if_fail (plug_in != NULL);
if (! message)
message = plug_in->args[0];
message = plug_in->prog;
if (gdisp_ID > 0)
gdisp = gimp_display_get_by_ID (plug_in->gimp, gdisp_ID);

View File

@ -95,6 +95,7 @@
#include "plug-in.h"
#include "plug-ins.h"
#include "plug-in-debug.h"
#include "plug-in-def.h"
#include "plug-in-message.h"
#include "plug-in-params.h"
@ -150,6 +151,8 @@ plug_in_init (Gimp *gimp)
*/
if (gimp->use_shm)
plug_in_shm_init (gimp);
plug_in_debug_init (gimp);
}
void
@ -159,6 +162,8 @@ plug_in_exit (Gimp *gimp)
g_return_if_fail (GIMP_IS_GIMP (gimp));
plug_in_debug_exit (gimp);
if (gimp->use_shm)
plug_in_shm_exit (gimp);
@ -257,14 +262,14 @@ plug_in_call_init (Gimp *gimp,
}
PlugIn *
plug_in_new (Gimp *gimp,
gchar *name)
plug_in_new (Gimp *gimp,
const gchar *prog)
{
PlugIn *plug_in;
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
g_return_val_if_fail (name != NULL, NULL);
g_return_val_if_fail (g_path_is_absolute (name), NULL);
g_return_val_if_fail (prog != NULL, NULL);
g_return_val_if_fail (g_path_is_absolute (prog), NULL);
plug_in = g_new0 (PlugIn, 1);
@ -281,13 +286,8 @@ plug_in_new (Gimp *gimp,
plug_in->starting_ext = FALSE;
plug_in->pid = 0;
plug_in->args[0] = g_strdup (name);
plug_in->args[1] = g_strdup ("-gimp");
plug_in->args[2] = NULL;
plug_in->args[3] = NULL;
plug_in->args[4] = NULL;
plug_in->args[5] = NULL;
plug_in->args[6] = NULL;
plug_in->name = g_path_get_basename (prog);
plug_in->prog = g_strdup (prog);
plug_in->my_read = NULL;
plug_in->my_write = NULL;
@ -329,18 +329,8 @@ plug_in_unref (PlugIn *plug_in)
if (plug_in->open)
plug_in_close (plug_in, TRUE);
if (plug_in->args[0])
g_free (plug_in->args[0]);
if (plug_in->args[1])
g_free (plug_in->args[1]);
if (plug_in->args[2])
g_free (plug_in->args[2]);
if (plug_in->args[3])
g_free (plug_in->args[3]);
if (plug_in->args[4])
g_free (plug_in->args[4]);
if (plug_in->args[5])
g_free (plug_in->args[5]);
g_free (plug_in->name);
g_free (plug_in->prog);
if (plug_in->progress)
plug_in_progress_end (plug_in);
@ -366,20 +356,29 @@ plug_in_prep_for_exec (gpointer data)
gboolean
plug_in_open (PlugIn *plug_in)
{
gint my_read[2];
gint my_write[2];
gchar **envp;
GError *error = NULL;
gint my_read[2];
gint my_write[2];
gchar **envp;
gchar *args[7], **argv, **debug_argv;
gchar *read_fd, *write_fd;
gchar *mode, *stm;
GError *error = NULL;
Gimp *gimp;
gboolean debug;
guint debug_flag;
guint spawn_flags;
g_return_val_if_fail (plug_in != NULL, FALSE);
gimp = plug_in->gimp;
/* Open two pipes. (Bidirectional communication).
*/
if ((pipe (my_read) == -1) || (pipe (my_write) == -1))
{
g_message ("pipe() failed: Unable to start Plug-In \"%s\"\n(%s)",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0]);
plug_in->name,
plug_in->prog);
return FALSE;
}
@ -413,9 +412,9 @@ plug_in_open (PlugIn *plug_in)
/* Remember the file descriptors for the pipes.
*/
plug_in->args[2] =
read_fd =
g_strdup_printf ("%d", g_io_channel_unix_get_fd (plug_in->his_read));
plug_in->args[3] =
write_fd =
g_strdup_printf ("%d", g_io_channel_unix_get_fd (plug_in->his_write));
/* Set the rest of the command line arguments.
@ -423,41 +422,67 @@ plug_in_open (PlugIn *plug_in)
*/
if (plug_in->query)
{
plug_in->args[4] = g_strdup ("-query");
mode = "-query";
debug_flag = GIMP_DEBUG_WRAP_QUERY;
}
else if (plug_in->init)
{
plug_in->args[4] = g_strdup ("-init");
mode = "-init";
debug_flag = GIMP_DEBUG_WRAP_INIT;
}
else
{
plug_in->args[4] = g_strdup ("-run");
mode = "-run";
debug_flag = GIMP_DEBUG_WRAP_RUN;
}
plug_in->args[5] = g_strdup_printf ("%d", plug_in->gimp->stack_trace_mode);
stm = g_strdup_printf ("%d", plug_in->gimp->stack_trace_mode);
#ifdef __EMX__
fcntl (my_read[0], F_SETFD, 1);
fcntl (my_write[1], F_SETFD, 1);
#endif
args[0] = plug_in->prog;
args[1] = "-gimp";
args[2] = read_fd;
args[3] = write_fd;
args[4] = mode;
args[5] = stm;
args[6] = NULL;
argv = args;
envp = gimp_environ_table_get_envp (plug_in->gimp->environ_table);
spawn_flags = G_SPAWN_LEAVE_DESCRIPTORS_OPEN | G_SPAWN_DO_NOT_REAP_CHILD;
debug = FALSE;
if (gimp->plug_in_debug)
{
debug_argv = plug_in_debug_argv (gimp, plug_in->name, debug_flag, args);
if (debug_argv)
{
debug = TRUE;
argv = debug_argv;
spawn_flags |= G_SPAWN_SEARCH_PATH;
}
}
/* Fork another process. We'll remember the process id so that we
* can later use it to kill the filter if necessary.
*/
envp = gimp_environ_table_get_envp (plug_in->gimp->environ_table);
if (! g_spawn_async (NULL, plug_in->args, envp,
G_SPAWN_LEAVE_DESCRIPTORS_OPEN |
G_SPAWN_DO_NOT_REAP_CHILD,
if (! g_spawn_async (NULL, argv, envp, spawn_flags,
plug_in_prep_for_exec, plug_in,
&plug_in->pid,
&error))
{
g_message ("Unable to run Plug-In: \"%s\"\n(%s)\n%s",
g_path_get_basename (plug_in->args[0]),
plug_in->args[0],
plug_in->name,
plug_in->prog,
error->message);
g_error_free (error);
return FALSE;
goto cleanup;
}
g_io_channel_unref (plug_in->his_read);
@ -478,7 +503,17 @@ plug_in_open (PlugIn *plug_in)
}
plug_in->open = TRUE;
return TRUE;
cleanup:
if (debug)
g_free (argv);
g_free (read_fd);
g_free (write_fd);
g_free (stm);
return plug_in->open;
}
void
@ -541,7 +576,7 @@ plug_in_close (PlugIn *plug_in,
}
if (STILL_ACTIVE == dwExitCode)
{
g_warning ("Terminating %s ...", plug_in->args[0]);
g_warning ("Terminating %s ...", plug_in->prog);
TerminateProcess ((HANDLE) plug_in->pid, 0);
}
}
@ -662,8 +697,8 @@ plug_in_recv_message (GIOChannel *channel,
"The dying Plug-In may have messed up GIMP's internal state.\n"
"You may want to save your images and restart GIMP\n"
"to be on the safe side."),
g_path_get_basename (plug_in->args[0]),
plug_in->args[0]);
plug_in->name,
plug_in->prog);
if (! plug_in->open)
plug_in_unref (plug_in);

View File

@ -39,8 +39,10 @@ struct _PlugIn
guint recurse : 1; /* Do we have an own GMainLoop? */
guint in_temp_proc : 1; /* Is the plug-in busy with a temp proc? */
guint starting_ext : 1; /* Does the plug-in wait for extension_ack?*/
pid_t pid; /* Plug-ins process id */
gchar *args[7]; /* Plug-ins command line arguments */
pid_t pid; /* Plug-in's process id */
gchar *name; /* Plug-in's name */
gchar *prog; /* Plug-in's full path name */
GIOChannel *my_read; /* App's read and write channels */
GIOChannel *my_write;
@ -64,29 +66,29 @@ struct _PlugIn
};
void plug_in_init (Gimp *gimp);
void plug_in_exit (Gimp *gimp);
void plug_in_init (Gimp *gimp);
void plug_in_exit (Gimp *gimp);
void plug_in_call_query (Gimp *gimp,
PlugInDef *plug_in_def);
void plug_in_call_init (Gimp *gimp,
PlugInDef *plug_in_def);
void plug_in_call_query (Gimp *gimp,
PlugInDef *plug_in_def);
void plug_in_call_init (Gimp *gimp,
PlugInDef *plug_in_def);
PlugIn * plug_in_new (Gimp *gimp,
gchar *name);
PlugIn * plug_in_new (Gimp *gimp,
const gchar *prog);
void plug_in_ref (PlugIn *plug_in);
void plug_in_unref (PlugIn *plug_in);
void plug_in_ref (PlugIn *plug_in);
void plug_in_unref (PlugIn *plug_in);
gboolean plug_in_open (PlugIn *plug_in);
void plug_in_close (PlugIn *plug_in,
gboolean kill_it);
gboolean plug_in_open (PlugIn *plug_in);
void plug_in_close (PlugIn *plug_in,
gboolean kill_it);
void plug_in_push (PlugIn *plug_in);
void plug_in_push (PlugIn *plug_in);
void plug_in_pop (void);
void plug_in_main_loop (PlugIn *plug_in);
void plug_in_main_loop_quit (PlugIn *plug_in);
void plug_in_main_loop (PlugIn *plug_in);
void plug_in_main_loop_quit (PlugIn *plug_in);
extern PlugIn *current_plug_in;

View File

@ -65,3 +65,18 @@ GIMP_PLUGIN_DEBUG=blur,query
GIMP_PLUGIN_DEBUG=blur,init
Same as above, but in the init phase of startup.
Hmm, but what about memory debuggers such as valgrind or purify? For those
you can set the following:
GIMP_PLUGIN_DEBUG_WRAP=name<,options>
This is similar to GIMP_PLUGIN_DEBUG. Only "query", "init", and "run"
are valid, and "on" defaults to simply "run"
GIMP_PLUGIN_DEBUG_WRAPPER=debugger
debugger refers to the debugger program, such as valgrind. You can
put command line options here too, they will be parsed like they do
in the shell.