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
To use a debugger on a C-language plug-in
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.
Examples using a debugger
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.
To get a backtrace for a plug-in in any language
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 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
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.
Quality of a backtrace
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.
More about logging levels
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.)
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:
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 plug-ins pid can be found out by invoking gimp-debug-resume.exe
without parameters. It shows the pid of all running processes.