There are various things which affect an entire application process. They are not all related, so are covered in separate subsections; some apply to all applications, others to specific functionality.
Summary
- Use libraries instead of subprocesses where possible.
- Use closed-loop subprocess management to keep track of when subprocesses exit.
- Do not use
sigaction()
: useg_unix_signal_add()
instead. - Do not use
sleep()
: useg_timeout_add_seconds()
instead. - Do not use
system()
: use libraries or single subprocesses instead. - Use
GApplication
andGOptionContext
to do command line parsing.
Subprocesses
Launching subprocesses is sometimes necessary to perform specific tasks, though where possible it is generally better to link against and use an appropriate library to perform the same task, as it eliminates a lot of potential failure points, simplifies passing data around (as passing data to subprocesses involves pipes, and is complex), and generally allows for greater interaction between the parent process and the task.
Subprocesses should not be used to implement functionality which could be implemented by D-Bus service daemons.
When using subprocesses, closed-loop management should be used, by monitoring the child process’ PID after sending it kill signals, and waiting until the child process terminates before proceeding with further processing. The alternative, open-loop management, sends signals and never checks to see if the child responded to them, which is more fragile.
To do this, use
g_spawn_async()
to spawn child processes, and
g_child_watch_add()
to set up a callback to be invoked when the child exits.
UNIX signals
The standard UNIX function for setting up signal handlers,
sigaction()
, must
not be used in GLib programs, as its callback must be re-entrancy safe, and no
GLib code is re-entrancy safe. Instead,
g_unix_signal_add()
should be used, which doesn’t require its callback to be re-entrancy safe.
Sleeping
The
sleep()
function must not be used in GLib code, as it blocks the current thread.
Instead,
g_timeout_add_seconds()
or
g_timeout_add()
should be used to schedule a callback to be invoked after a period of time; in
the mean time, events can continue being processed by the main context.
Shell commands
The system()
function must not be
used. It is extremely prone to
shell injection vulnerabilities,
and any functionality which can be implemented using it can be implemented
using libraries directly or, if that is not possible, spawning individual
subprocesses.
For example, instead of calling system (g_strdup_printf ("mv %s %s", file_path1, file_path2))
, use
g_file_move()
.
In this situation, using system()
exposes a shell injection vulnerability,
and will not work with paths containing spaces in any case.
Command line parsing
Command line parsing should be implemented using
GApplication
and
GOptionContext
,
rather than being implemented manually or using another library (such as
popt).
By using GOptionContext
, command line parsing follows the standard format
used by most Linux applications. It gives automatic support for --help
output, and short and long option parsing.
An example of using GApplication
together with GOptionContext
is
here.