Global Variables
A handful of global structures carry state across the whole application. Know these before you start; misuse of them (especially the locks) has caused real shipped bugs.
gfit
gfit is the currently loaded image. It is declared in src/core/siril.h.
Changed in version 1.5: gfit is now a pointer: extern fits *gfit;. In 1.4 it was a
value: extern fits gfit;. When porting an old patch, &gfit becomes
gfit and params->fit = &gfit; becomes params->fit = gfit;.
The fits structure (struct ffit) holds the pixel data (data for
16-bit, fdata for float — the two are mutually exclusive, selected by
type), the per-layer pointers (pdata / fpdata), the FITS keywords,
the statistics cache (stats), the ICC profile, an optional image mask
(see Masks), and — as its last member — a read/write lock.
The fits rwlock
Every fits embeds a GRWLock rwlock as its last field (a static
assertion enforces the position). It guards concurrent access to the pixel
data and metadata of public fits — currently only gfit — from the
processing worker and from Python connection threads.
The rules, transcribed from the comment in siril.h:
Locking is done in high-level code only: the generic workers (Generic workers), the simple threaded functions run directly via
start_in_new_thread, and the Python command handlers.It must not be taken in low-level fits-handling functions (format loaders,
copyfits, directdata/fdatamanipulation). Locking there is likely to cause deadlocks.The lock is initialised for free by
calloc/zero-init of thefits, and is never copied or overwritten bycopyfits().Always unlock with the same flavour you locked (
g_rw_lock_reader_lock↔g_rw_lock_reader_unlock). GLib does not assert on mismatch, and a reader-lock/writer-unlock mismatch has shipped as a data-corruption bug.
Important
Worker hooks run with the fits already locked on your behalf by the
worker. An image_hook / mask_hook must not take the fits lock on
the fits it was handed — the lock is non-recursive, so you would instantly
self-deadlock on the in-place path. See Locking.
com
com (struct cominf, in siril.h) is the global core state
structure.
Warning
Avoid adding members to com. For state that must outlive a single
operation, prefer a module-static variable in the file that owns it —
the C equivalent of a class variable. Only add to com when there is no
reasonable alternative.
The members you will actually reach for:
com.pref— the whole preferences tree (seesettings.c,h). Read under thepref_rwlockreader lock, which the workers already hold for you for the duration of a job.com.max_thread— the total thread budget for parallel execution. Do not read this directly inside a worker hook; use the thread count the worker hands you (see Threading).com.headless— TRUE forsiril-cli(no GUI at all).com.script— a script is executing (always TRUE when headless).com.python_script/com.python_command— a Python script is running / Python is currently running a Siril command.com.seq— the currently loaded sequence.com.uniq— the currently loaded single image, when not in a sequence.com.selection— the selection rectangle (all four fields are updated atomically undercom.mutex).com.wd— the working directory.com.stars— the detected star list (guarded bycom.stars_lock).
Locks that live in com
Several synchronisation primitives are members of com:
com.mutex, com.env_mutex, com.histogram_mutex, com.pref_rwlock
and com.stars_lock. Their duties, who may take them and — critically —
where they must not be taken are documented once, authoritatively, in
Locking. Do not reason about them from here; that chapter is the
single source of truth (it also covers the per-fits rwlock above).
gui
gui (struct guiinf, now in src/gui-gtk4/gui_state.h) holds
GTK-side display state: the per-viewport image views and tiles, zoom, the ROI,
render buffers and their cairo_mutex.
Changed in version 1.5: guiinfo moved out of siril.h into src/gui-gtk4/gui_state.h
as part of the GUI separation. It is never referenced outside
src/gui-gtk4. Core code that needs a GUI effect goes through
gui_iface instead — see gui_iface in depth.