mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-07-03 17:33:25 +00:00
devel-docs: move debug-plug-ins.txt to gimp-web-devel.
Now in the "Resource development" section of the developer website under resource/debug-plug-ins/.
This commit is contained in:
parent
9716768bb1
commit
114d0f35df
2 changed files with 0 additions and 309 deletions
|
@ -8,7 +8,6 @@ EXTRA_DIST = \
|
||||||
HACKING.md \
|
HACKING.md \
|
||||||
README.md \
|
README.md \
|
||||||
contexts.txt \
|
contexts.txt \
|
||||||
debug-plug-ins.txt \
|
|
||||||
includes.txt \
|
includes.txt \
|
||||||
parasites.txt \
|
parasites.txt \
|
||||||
tagging.txt \
|
tagging.txt \
|
||||||
|
|
|
@ -1,308 +0,0 @@
|
||||||
Debugging Plug-ins
|
|
||||||
==================
|
|
||||||
|
|
||||||
Eeek! The plug-in you're working on has a bug in it! And the fix isn't
|
|
||||||
completely obvious, so you want to use a debugger to see what is going on.
|
|
||||||
But hmm, how does one start a plug-in under a debugger if GIMP is the one
|
|
||||||
who is starting the plug-in...
|
|
||||||
|
|
||||||
To address this issue, libgimp has some hooks controlled by the
|
|
||||||
GIMP_PLUGIN_DEBUG environment variable at runtime.
|
|
||||||
|
|
||||||
GIMP_PLUGIN_DEBUG lets you arrange that a plug-in suspends when it starts,
|
|
||||||
and then you can start a debugger and attach the debugger to the pid of the
|
|
||||||
plug-in.
|
|
||||||
|
|
||||||
GIMP_PLUGIN_DEBUG also lets you arrange for log messages of levels WARNING,
|
|
||||||
CRITICAL, and ERROR (from the plug-in, GIMP libraries, and GLib libraries)
|
|
||||||
to be fatal and generate a backtrace at that point (also called
|
|
||||||
a stack trace, similar to that generated in a debugger using the 'bt' command.)
|
|
||||||
|
|
||||||
When GIMP_PLUGIN_DEBUG is not defined, depending on how other GLib environment
|
|
||||||
variables are defined, a plug-in may quietly execute past
|
|
||||||
warning and critical logged events, and only terminate on a ERROR logged event
|
|
||||||
(without a backtrace), or on a soft or hard fault such as a memory exception
|
|
||||||
(possibly producing a core dump that you can examine using a debugger.)
|
|
||||||
|
|
||||||
|
|
||||||
Format of GIMP_PLUGIN_DEBUG:
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
GIMP_PLUGIN_DEBUG=name<,options>
|
|
||||||
|
|
||||||
"name" specifies the name of the plug-in that you wish to debug,
|
|
||||||
or "all" to debug every plug-in. See below "Plug-in names".
|
|
||||||
|
|
||||||
"options" is zero or more of the following options, separated by :'s
|
|
||||||
|
|
||||||
run: suspend the plug-in when its run func is called.
|
|
||||||
query: suspend the plug-in when its query func is called.
|
|
||||||
init: suspend the plug-in when its init func is called.
|
|
||||||
quit: suspend the plug-in when its quit func is called.
|
|
||||||
pid: just print the pid of the plug-in on run_proc.
|
|
||||||
fatal-warnings: similar to "gimp --g-fatal-warnings" on the command line,
|
|
||||||
but for the plugin process
|
|
||||||
fw: shorthand for above.
|
|
||||||
fatal-criticals: make CRITICAL level messages fatal (but not WARNING)
|
|
||||||
|
|
||||||
In the absence of an options string, only ERRORs are fatal and generate
|
|
||||||
a backtrace according to stack-trace-mode
|
|
||||||
|
|
||||||
|
|
||||||
To use a debugger on a C-language plug-in:
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
0. Ensure GIMP was built with debugging information (gcc -g)
|
|
||||||
|
|
||||||
1. In a terminal, start GIMP with the environment variable GIMP_PLUGIN_DEBUG set
|
|
||||||
( e.g. ">GIMP_PLUGIN_DEBUG=blur,on gimp" )
|
|
||||||
|
|
||||||
2. In another terminal, start a debugger (gdb, lldb, or other) and load the plug-in
|
|
||||||
program into the debugger. Loading only loads the debug symbols.
|
|
||||||
( e.g. ">gdb blur" )
|
|
||||||
|
|
||||||
3. Invoke the plug-in procedure in GIMP. GIMP will start the plug-in
|
|
||||||
process, then suspend it and print the pid of the plug-in process
|
|
||||||
to the terminal where you started GIMP.
|
|
||||||
|
|
||||||
4. In the debugger, attach to the pid of the plug-in process.
|
|
||||||
(e.g. "gdb> attach <pid>")
|
|
||||||
Expect the debugger to say where the plug-in is suspended.
|
|
||||||
|
|
||||||
5. In the debugger, set breakpoints (or examine memory, or step, etc.)
|
|
||||||
|
|
||||||
6. Windows: resume the plug-in process with "gimp-debug-resume.exe <pid>"
|
|
||||||
|
|
||||||
Linux and Unix-like: the gdb `continue` command might resume the
|
|
||||||
attached process. Possibly you will have to send a SIGCONT signal:
|
|
||||||
|
|
||||||
kill -SIGCONT <pid>
|
|
||||||
|
|
||||||
7. In the debugger, enter "continue". Expect the plug-in to resume under
|
|
||||||
control of the debugger and pause at breakpoints.
|
|
||||||
(e.g. "gdb> continue")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Examples using a debugger:
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
GIMP_PLUGIN_DEBUG=blur
|
|
||||||
|
|
||||||
When the blur plug-in's run func is called (the run phase),
|
|
||||||
GIMP suspends it and prints to the console:
|
|
||||||
|
|
||||||
(blur:9000): LibGimp-DEBUG: Waiting for debugger...
|
|
||||||
|
|
||||||
9000 is the pid of the new plug-in process. You can start your debugger,
|
|
||||||
attach to the plug-in, set breakpoints/watches/etc. and continue from there.
|
|
||||||
Using gdb command "continue" will resume the plugin.
|
|
||||||
|
|
||||||
Expect the plugin to execute until it hits a breakpoint or until a WARNING
|
|
||||||
or worse event is logged or until a hard fault such as a memory violation.
|
|
||||||
Then the debugger will be back in control.
|
|
||||||
|
|
||||||
GIMP_PLUGIN_DEBUG=blur,on
|
|
||||||
GIMP_PLUGIN_DEBUG=blur,run:fatal-warnings
|
|
||||||
|
|
||||||
Same effect as above.
|
|
||||||
|
|
||||||
GIMP_PLUGIN_DEBUG=blur,pid
|
|
||||||
|
|
||||||
Prints:
|
|
||||||
|
|
||||||
(blur:9000): LibGimp-DEBUG: Here I am!
|
|
||||||
|
|
||||||
This simply prints the pid but doesn't suspend the plug-in. It is a
|
|
||||||
convenience for a plug-in having a GUI. The GUI starts up and waits
|
|
||||||
for user input. When you attach, you will find the plug-in waiting
|
|
||||||
in the event loop.
|
|
||||||
|
|
||||||
GIMP_PLUGIN_DEBUG=blur,query
|
|
||||||
GIMP_PLUGIN_DEBUG=blur,init
|
|
||||||
GIMP_PLUGIN_DEBUG=blur,quit
|
|
||||||
|
|
||||||
Same effect as for "run", but instead libgimp suspends the plug-in before
|
|
||||||
one of a plugin's phases: query, init, run, quit
|
|
||||||
E.G. when it is queried or init'ed on GIMP startup.
|
|
||||||
|
|
||||||
|
|
||||||
To get a backtrace for a plug-in in any language:
|
|
||||||
-------------------------------------------------
|
|
||||||
|
|
||||||
0. Ensure GIMP (and all libraries you want details for)
|
|
||||||
were built with debugging information (gcc -g)
|
|
||||||
|
|
||||||
1. In a terminal, start GIMP with the environment variable GIMP_PLUGIN_DEBUG set
|
|
||||||
( e.g. ">GIMP_PLUGIN_DEBUG=all,fatal-criticals gimp" )
|
|
||||||
Expect GIMP to start normally.
|
|
||||||
|
|
||||||
2. In GIMP, do something that would invoke a plugin.
|
|
||||||
|
|
||||||
Whenever the specified plug-in processes generate log events of
|
|
||||||
the specified levels or worse, libgimp will print or offer to print
|
|
||||||
(depends on stack-trace-mode) a backtrace, and then terminate the plug-in.
|
|
||||||
The GIMP app will usually continue to run.
|
|
||||||
|
|
||||||
For interpreted language plug-ins, the backtrace will include many frames
|
|
||||||
from the interpreter and modules such as PyGObject. Exceptions in the
|
|
||||||
interpreted language may print on their own and not generate log events
|
|
||||||
to be caught by GIMP_PLUGIN_DEBUG. But log events from the interpreter
|
|
||||||
calling out (to LibGimp and GLib) can generate backtraces.
|
|
||||||
|
|
||||||
|
|
||||||
GIMP_PLUGIN_DEBUG and stack-trace-mode
|
|
||||||
--------------------------------------
|
|
||||||
|
|
||||||
GIMP_PLUGIN_DEBUG=all,fatal-warning only makes the machinery *consider*
|
|
||||||
generating a backtrace, for more log events. The 'stack-trace-mode' pertains.
|
|
||||||
|
|
||||||
The GIMP app on the command line takes a flag:
|
|
||||||
|
|
||||||
--stack-trace-mode [never, query, always]
|
|
||||||
|
|
||||||
When the GIMP app forks a plugin process, it passes that arg to the plugin,
|
|
||||||
and the arg controls how a backtrace is printed.
|
|
||||||
|
|
||||||
The default is "query", which means libgimp will ask you:
|
|
||||||
"[E]xit [S]tacktrace [P]roceed"
|
|
||||||
(similar to the GLib default handler for ERROR log events.)
|
|
||||||
|
|
||||||
"always" means libgimp prints a backtrace (and then the plugin terminates.)
|
|
||||||
|
|
||||||
"never" means libgimp does not print a backtrace, only a message. But for
|
|
||||||
GIMP_PLUGIN_DEBUG=all,fatal-warning, the plugin terminates on the first WARNING.
|
|
||||||
|
|
||||||
|
|
||||||
Examples getting a backtrace on logged events:
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
GIMP_PLUGIN_DEBUG=blur,fatal-warnings
|
|
||||||
|
|
||||||
The blur plug-in will run until the first logged WARNING or worse,
|
|
||||||
from the plug-in, GIMP libraries, or GLib libraries.
|
|
||||||
Then a backtrace can print to the console and the blur plug-in terminate.
|
|
||||||
Usually you will also see a message from the main GIMP app
|
|
||||||
saying the plugin aborted without returning a value.
|
|
||||||
|
|
||||||
GIMP_PLUGIN_DEBUG=all,fatal-criticals
|
|
||||||
|
|
||||||
Every plug-in (whether you invoked it from the GIMP GUI or it was called
|
|
||||||
by another plug-in) will run until the first logged CRITICAL or worse,
|
|
||||||
from the plug-in, GIMP libraries, or GLib libraries.
|
|
||||||
Then, as above, a backtrace can print etc.
|
|
||||||
|
|
||||||
GIMP_PLUGIN_DEBUG=all
|
|
||||||
|
|
||||||
As above, for all plugins, but only for a logged ERROR.
|
|
||||||
|
|
||||||
|
|
||||||
Quality of a backtrace
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
A detailed backtrace depends on:
|
|
||||||
|
|
||||||
1) building GIMP and dependencies with debug info enabled
|
|
||||||
2) having a debugger installed
|
|
||||||
|
|
||||||
When a debugger is not installed, a backtrace may lack details such as
|
|
||||||
function names and line numbers.
|
|
||||||
|
|
||||||
|
|
||||||
More about logging levels
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
See https://developer.gnome.org/glib/stable/glib-Message-Logging.html
|
|
||||||
|
|
||||||
Level Engendered by
|
|
||||||
-----------------------
|
|
||||||
WARNING g_warning().
|
|
||||||
CRITICAL g_return_value_if_fail() or g_return_if_fail().
|
|
||||||
ERROR g_assert() or g_error().
|
|
||||||
|
|
||||||
Use of logging levels is by convention, and libraries that GIMP uses may not
|
|
||||||
follow conventions.
|
|
||||||
|
|
||||||
Generally speaking...
|
|
||||||
|
|
||||||
WARNINGs are common but don't signify much. They might mean that your plug-in
|
|
||||||
code does not understand, or is sloppy with, the GIMP API.
|
|
||||||
|
|
||||||
CRITICALs are rare but more significant. They usually mean that GIMP will
|
|
||||||
attempt to continue past an errant condition. The GLib function
|
|
||||||
g_return_value_if_fail() is often used in GIMP code as a precondition,
|
|
||||||
required to succeed before a GIMP function executes its body,
|
|
||||||
the function returning early when the precondition fails.
|
|
||||||
|
|
||||||
ERRORs are usually dire. They always terminate a plug-in.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Plug-in names
|
|
||||||
-------------
|
|
||||||
|
|
||||||
A plug-in may register many PDB procedures. Use the plug-in name, not a
|
|
||||||
procedure-name, e.g. "file-psd" not "file-psd-save". When a plug-in is "run",
|
|
||||||
one of its PDB procedures is run, and all of its PDB procedures
|
|
||||||
are covered by a GIMP_PLUGIN_DEBUG definition.
|
|
||||||
|
|
||||||
A name is usually the name of the executable file, including any suffix.
|
|
||||||
Examples: "file-psd" or "foggify.py" or on some platforms "foo.exe."
|
|
||||||
|
|
||||||
Usually an interpreted plug-in has a hashbang on the first line
|
|
||||||
e.g. "#!/usr/bin/env python3" in the first line of foo.py.
|
|
||||||
Then the file is executable, GIMP forks that file, and the Linux loader
|
|
||||||
invokes the interpreter.
|
|
||||||
|
|
||||||
However, GIMP still allows a plug-in source
|
|
||||||
to lack a hashbang (and it is not technically "an executable")
|
|
||||||
but then GIMP forks the interpreter, passing the script filename.
|
|
||||||
In this case, you must still use the name of the script file e.g. "foo.py"
|
|
||||||
in GIMP_PLUGIN_DEBUG.
|
|
||||||
|
|
||||||
(Since forever, GIMP does not understand Python packages.
|
|
||||||
GIMP only installs Python plugins from directories named like foo/foo.py.
|
|
||||||
A directory that is a Python package (having an __init__.py file)
|
|
||||||
will be read by GIMP at startup, but GIMP will only install one plugin
|
|
||||||
from that directory, and only if the .py file is named like the directory.)
|
|
||||||
|
|
||||||
|
|
||||||
Finding plug-in source by name
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
A GIMP supported C language plug-in's source should be in a similar-named
|
|
||||||
directory in the GIMP repository. For example, "file-psd" is a directory
|
|
||||||
(but there is no "file-psd.c".)
|
|
||||||
|
|
||||||
An interpreted plug-in is *installed* in a directory of a similar name
|
|
||||||
e.g. "plug-ins/foggify/foggify.py".
|
|
||||||
But in the GIMP repository, foggify.py does not live at foggify/foggify.py
|
|
||||||
but at plug-ins/python/foggify.py .
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Examples using other debug tools:
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
Windows:
|
|
||||||
--------
|
|
||||||
|
|
||||||
When compiled with Windows, a plug-in process is halted by Windows functions.
|
|
||||||
It must be resumed externally by invoking gimp-debug-resume.exe <pid>
|
|
||||||
The plug-ins pid can be found out by invoking gimp-debug-resume.exe
|
|
||||||
without parameters. It shows the pid of all running processes.
|
|
Loading…
Add table
Add a link
Reference in a new issue