Resource choosers in plugins throw CRITICAL on second invocation, using freed proxy
Environment/Versions
2.99 self-built master
Description of the bug
In stderr:
gimp_value_array_new_from_types_valist .... (varying warnings)
then a plugin crashes
Reproduction
Is the bug reproducible? Always
Reproduction steps:
- Image>New
- Filters>Render>Fractals>Fractal Explorer
- click on "Colors" tab
- click on the gradient icon (a button), expect a chooser dialog
- choose a gradient, then OK
- for the second time, click on the gradient icon
Expected result: chooser dialog again.
Actual result: as above.
Discussion
Discovered in #10536 (closed), one of several bugs, which must be fixed first to test this.
The bug involves the architecture of plugins. Here I discuss my understanding, which might not be correct. This discussion should also be in a forthcoming commit and MR.
The bug is in libgimp/gimpplugin.c. It improperly destroys proxies after each run of a temporary procedure. Proxies should probably live as long as the main procedure of a plugin.
The FE plugin's main procedure was given a reference to a proxy in a temporary procedure callback, has retained a reference to the proxy, and is passing it back after the proxy has been destroyed.
Background: Procedures of a plugin are registered in the PDB and called by "remote procedure call" across a wire, from one process to another. Proxies are objects used to identify remote objects across the wire (on the wire, they are unique integer ID's.) Proxies are used for GIMP image, item, resource... objects.
A plugin can have main (or "real") and temporary procedures. The main procedure of a plugin is only run once, and determines the life of the plugin's execution.
Temporary procedures can only be run when the main plugin procedure is running. Temporary procedures can run many times. The main and temporary procedures are executed in the same process, and can share variables.
Most temporary procedures belong to main procedures which are extensions. An extension is long-lived. The script-fu, help, and on-line systems are the primary extensions.
Other temporary procedures are used for GUI. A temporary procedure is callback'd from a remote GUI dialog (in the GIMP app.) The temporary procedure can pass proxies to the main procedure (in the plugin). The main procedure may retain a reference to a proxy, but should not ref it, and instead rely on its continued existence for the life of the plugin. (See comments in gimpplugin.c: "a plug-in MUST NOT ref a proxy" An alternative design is to let plugins ref and unref proxies, and make gimpplugin.c less stringent.)
Most temporary procedures remain published in the PDB for the lifetime of the GIMP app. More precisely, while the plugin's file exists and GIMP has queried it. Temporary procedures can be in the PDB even while the plugin itself is not running. Temporary procedures can also be ephemeral in the PDB: registered and removed by the running main procedure of the plugin. That happens for temporary procedures for callback from GUI remote dialogs.