GIMP Script-Fu Image Buffer Thread Safety
When external Script-Fu plugins interact with GIMP image buffers, thread safety is guaranteed through a layered architecture involving process isolation, serialized Inter-Process Communication (IPC), procedural database synchronization, and GEGL buffer abstractions. Rather than granting plugins direct pointer access to shared memory, GIMP mediates all image modifications through controlled access layers that prevent race conditions, memory corruption, and concurrent write collisions.
Process Isolation and IPC Serialization
The primary defense against concurrent memory conflicts is that Script-Fu runs as an independent executable rather than an internal thread within the primary GIMP address space. Communication between the Script-Fu interpreter and the GIMP core occurs through an IPC wire protocol using operating system pipes.
Because calls to query or modify an image are transmitted as discrete messages across this boundary, image operations are naturally serialized:
- Asynchronous Message Passing: The plugin requests actions via the Procedural Database (PDB).
- Core-Side Dispatch: The core GIMP process receives these requests and dispatches them inside its own synchronization boundaries, eliminating direct memory contention between the plugin's Scheme runtime and GIMP's internal rendering threads.
GEGL Buffer Tile Locking and Concurrency Control
In modern versions of GIMP (2.10 and GIMP 3.0), image data is managed
by the Generic Graphics Library (GEGL). The underlying image storage
(GeglBuffer) is divided into discrete tiles. GEGL provides
built-in concurrency control across these tiles:
- Tile Locks: When a plugin initiates reads or writes via GEGL-backed PDB procedures, GEGL acquires read or write locks on the affected tiles.
- Thread-Safe Iteration: If parallel worker threads within GIMP are reading from an area, write requests wait or operate on distinct tile copies to prevent dirty reads.
- Copy-On-Write (COW): GEGL utilizes copy-on-write semantics. If an operation duplicates a buffer or creates a reference, shared data is only duplicated in memory when a write occurs, protected by reference-counting atomics.
Shadow Buffers and Atomic Commits
GIMP prevents scripts from directly mutating active display buffers in-place. Instead, modifications follow a shadow buffer pattern:
- Pixel Fetching: Plugins access pixel regions using procedural calls that return copies of the data or map temporary local buffers.
- Shadow Writing: Modifications are applied to a dedicated "shadow" buffer associated with the target drawable.
- Merging: Once the operation completes, the script
calls procedures such as
gimp_drawable_merge_shadow. The GIMP core locks the target drawable, commits the shadow pixel updates into the primary buffer, marks the undo step, and invalidates the affected display regions atomically.
PDB and Main Context Synchronization
Within the GIMP core process, calls coming from the Script-Fu IPC
channel are funneled through the GIMP Main Loop context using GLib
primitives (GSource, GMutex). Even if GIMP
employs a multi-threaded rendering engine for viewport updates and
filter execution, the execution of plugin-initiated image mutations is
coordinated with the undo stack and active processing graphs. This
guarantees that image buffers remain in a valid, deterministic state
throughout the plugin execution lifecycle.