And make callers check the return value as well. This helps error out early for
invalid environment variables.
That is desirable because it could lead to deadlocks. This can happen when
resetting logging after fork() reports translated errors because gettext
functions are not reentrant. Well, it is not limited to resetting logging after
fork(), it can be any translation at that phase, but parsing environment
variables is easy to make fail on purpose to show the result, it can also happen
just due to a typo.
Before this commit it is possible to deadlock the daemon on startup
with something like:
LIBVIRT_LOG_FILTERS='1:*' LIBVIRT_LOG_OUTPUTS=1:stdout libvirtd
where filters are used to enable more logging and hence make the race less rare
and outputs are set to invalid
Combined with the previous patches this changes
the following from:
...
<deadlock>
to:
...
libvirtd: initialisation failed
The error message is improved in future commits and is also possible thanks to
this patch.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
if (virErrorInitialize() < 0)
goto error;
- virLogSetFromEnv();
+ if (virLogSetFromEnv() < 0)
+ goto error;
#ifdef WITH_LIBINTL_H
if (!bindtextdomain(PACKAGE, LOCALEDIR))
goto error;
}
- virLogSetFromEnv();
+ if (virLogSetFromEnv() < 0)
+ goto error;
virNetTLSInit();
}
/* Initialize logging */
- virLogSetFromEnv();
+ if (virLogSetFromEnv() < 0)
+ exit(EXIT_FAILURE);
while (1) {
int c;
virFileActivateDirOverrideForProg(argv[0]);
/* Initialize the log system */
- virLogSetFromEnv();
+ if (virLogSetFromEnv() < 0)
+ exit(EXIT_FAILURE);
uri_str = argv[1];
VIR_DEBUG("Using URI %s", uri_str);
virFileActivateDirOverrideForProg(argv[0]);
/* Initialize the log system */
- virLogSetFromEnv();
+ if (virLogSetFromEnv() < 0)
+ exit(EXIT_FAILURE);
/* clear the environment */
environ = NULL;
VIR_FORCE_CLOSE(null);
/* Initialize full logging for a while */
- virLogSetFromEnv();
+ if (virLogSetFromEnv() < 0)
+ goto fork_error;
if (cmd->pidfile &&
virPipe(pipesync) < 0)
return -1;
/* If there are some environment variables defined, use those instead */
- virLogSetFromEnv();
+ if (virLogSetFromEnv() < 0)
+ return -1;
/*
* Command line override for --verbose
*
* Sets virLogDefaultPriority, virLogFilters and virLogOutputs based on
* environment variables.
+ *
+ * This function might fail which should also make the caller fail.
*/
-void
+int
virLogSetFromEnv(void)
{
const char *debugEnv;
if (virLogInitialize() < 0)
- return;
+ return -1;
debugEnv = getenv("LIBVIRT_DEBUG");
- if (debugEnv && *debugEnv)
- virLogSetDefaultPriority(virLogParseDefaultPriority(debugEnv));
+ if (debugEnv && *debugEnv) {
+ int priority = virLogParseDefaultPriority(debugEnv);
+ if (priority < 0 ||
+ virLogSetDefaultPriority(priority) < 0)
+ return -1;
+ }
debugEnv = getenv("LIBVIRT_LOG_FILTERS");
- if (debugEnv && *debugEnv)
- virLogSetFilters(debugEnv);
+ if (debugEnv && *debugEnv &&
+ virLogSetFilters(debugEnv))
+ return -1;
debugEnv = getenv("LIBVIRT_LOG_OUTPUTS");
- if (debugEnv && *debugEnv)
- virLogSetOutputs(debugEnv);
+ if (debugEnv && *debugEnv &&
+ virLogSetOutputs(debugEnv))
+ return -1;
+
+ return 0;
}
char *virLogGetOutputs(void);
virLogPriority virLogGetDefaultPriority(void);
int virLogSetDefaultPriority(virLogPriority priority);
-void virLogSetFromEnv(void);
+int virLogSetFromEnv(void) G_GNUC_WARN_UNUSED_RESULT;
void virLogOutputFree(virLogOutput *output);
void virLogOutputListFree(virLogOutput **list, int count);
void virLogFilterFree(virLogFilter *filter);
if (virErrorInitialize() < 0)
return EXIT_FAILURE;
- virLogSetFromEnv();
+ if (virLogSetFromEnv() < 0)
+ return EXIT_FAILURE;
+
if (!getenv("LIBVIRT_DEBUG") && !virLogGetNbOutputs()) {
if (!(output = virLogOutputNew(virtTestLogOutput, virtTestLogClose,
&testLog, VIR_LOG_DEBUG,