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
GIMP_PLUGIN_DEBUG also lets you arrange for log messages of levels
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.)
“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
Ensure GIMP was built with debugging information (
In a terminal, start GIMP with the environment variable
GIMP_PLUGIN_DEBUGset ( e.g.
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.
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.
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.
In the debugger, set breakpoints (or examine memory, or step, etc.)
Windows: resume the plug-in process with
Linux and Unix-like: the gdb
continuecommand might resume the attached process. Possibly you will have to send a SIGCONT signal:
kill -SIGCONT <pid>
In the debugger, enter “continue”. Expect the plug-in to resume under control of the debugger and pause at breakpoints. (e.g.
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.
Same effect as above.
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.
Ensure GIMP (and all libraries you want details for) were built with debugging information (
In a terminal, start GIMP with the environment variable
GIMP_PLUGIN_DEBUGset ( e.g.
>GIMP_PLUGIN_DEBUG=all,fatal-criticals gimp) Expect GIMP to start normally.
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=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.
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.
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.
As above, for all plugins, but only for a logged ERROR.
A detailed backtrace depends on:
- building GIMP and dependencies with debug info enabled
- having a debugger installed
When a debugger is not installed, a backtrace may lack details such as function names and line numbers.
Use of logging levels is by convention, and libraries that GIMP uses may not follow conventions.
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.
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
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”
(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.)
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 .
Hmm, but what about memory debuggers such as valgrind or purify? For those you can set the following:
This is similar to `GIMP_PLUGIN_DEBUG`. Only "query", "init", and "run" are valid, and "on" defaults to simply "run"
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.
When compiled with Windows, a plug-in process is halted by Windows functions.
It must be resumed externally by invoking
The pid of the running plug-in can be found by invoking gimp-debug-resume.exe
without parameters. It shows the pid of all running processes. Another option
for finding the pid is checking the terminal where GIMP is running, see below.
For this example we will use the screenshot plug-in and assume that you are using the MINGW64 profile of MSYS2. Instead of MINGW64 you can also use e.g. CLANG64 or UCRT if you are using that for developing.
- Open three (3) MINGW64 terminals.
- In the first terminal start GIMP with:
- In the second terminal load gdb with the plug-in, using its path in the prefix you set for your GIMP build:
- In GIMP start your plug-in so that it’s run function will be called.
- You should see something in the first terminal like this:
(screenshot.exe:8992): LibGimp-DEBUG: 16:44:50.894: Debugging (restart externally): 8992
The number at the end is the pid of the plug-in. 6. In the second terminal, in gdb, attach it to the pid of the plug-in process:
(gdb) attach 8992
Note that (gdb) is the prompt of the debugger, not something that you need to type yourself. Expect the debugger to say where the plug-in is suspended. 7. In the debugger, set breakpoints etc. as needed. 8. We now need to resume the plug-in. In the third terminal type the following, but adjust the number to the pid that you see in your first terminal:
Note that apparently gimp-debug-resume is currently not copied/installed to
your prefix, meaning that you will have to start it from your build directory.
10. In the second terminal in gdb type
11. The plug-in should resume running until a breakpoint or crash happens…