mirror of https://github.com/GNOME/gimp.git
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
|
@ -8,7 +8,6 @@ EXTRA_DIST = \
|
|||
HACKING.md \
|
||||
README.md \
|
||||
contexts.txt \
|
||||
debug-plug-ins.txt \
|
||||
includes.txt \
|
||||
parasites.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…
Reference in New Issue