https://www.redhat.com/archives/libvir-list/2020-August/msg00596.html Doing malloc/free after fork is technically not allowed in POSIX and deadlocks[1] with musl libc. [1]: https://gitlab.com/libvirt/libvirt/-/issues/52 Signed-off-by: Natanael Copa --- src/util/vircommand.c | 4 ++-- src/util/virlog.c | 44 +++++++++++++++++++++++++++++++++---------- src/util/virlog.h | 1 + 3 files changed, 37 insertions(+), 12 deletions(-) diff -ur src/util/vircommand.c src/util/vircommand.c --- src/util/vircommand.c +++ src/util/vircommand.c @@ -304,7 +304,7 @@ /* Make sure any hook logging is sent to stderr, since child * process may close the logfile FDs */ logprio = virLogGetDefaultPriority(); - virLogReset(); + virLogResetWithoutFree(); virLogSetDefaultPriority(logprio); /* Clear out all signal handlers from parent so nothing @@ -897,7 +897,7 @@ goto fork_error; /* Close logging again to ensure no FDs leak to child */ - virLogReset(); + virLogResetWithoutFree(); if (cmd->env) execve(binary, cmd->args, cmd->env); diff -ur src/util/virlog.h src/util/virlog.h --- src/util/virlog.h +++ src/util/virlog.h @@ -168,6 +168,7 @@ void virLogLock(void); void virLogUnlock(void); int virLogReset(void); +int virLogResetWithoutFree(void); int virLogParseDefaultPriority(const char *priority); int virLogPriorityFromSyslog(int priority); void virLogMessage(virLogSourcePtr source, --- src/util/virlog.c 2021-05-03 11:02:51.455354200 +0200 +++ src/util/virlog.c 2021-05-08 11:56:58.414314487 +0200 @@ -108,8 +108,8 @@ */ static virLogPriority virLogDefaultPriority = VIR_LOG_DEFAULT; -static void virLogResetFilters(void); -static void virLogResetOutputs(void); +static void virLogResetFilters(bool freemem); +static void virLogResetOutputs(bool freemem); static void virLogOutputToFd(virLogSource *src, virLogPriority priority, const char *filename, @@ -284,8 +284,30 @@ return -1; virLogLock(); - virLogResetFilters(); - virLogResetOutputs(); + virLogResetFilters(true); + virLogResetOutputs(true); + virLogDefaultPriority = VIR_LOG_DEFAULT; + virLogUnlock(); + return 0; +} + +/** + * virLogResetWithoutFree: + * + * Reset the logging module to its default initial state, but avoid doing + * free() so it can be used after fork and before exec. + * + * Returns 0 if successful, and -1 in case or error + */ +int +virLogResetWithoutFree(void) +{ + if (virLogInitialize() < 0) + return -1; + + virLogLock(); + virLogResetFilters(false); + virLogResetOutputs(false); virLogDefaultPriority = VIR_LOG_DEFAULT; virLogUnlock(); return 0; @@ -324,9 +346,10 @@ * Removes the set of logging filters defined. */ static void -virLogResetFilters(void) +virLogResetFilters(bool freemem) { - virLogFilterListFree(virLogFilters, virLogNbFilters); + if (freemem) + virLogFilterListFree(virLogFilters, virLogNbFilters); virLogFilters = NULL; virLogNbFilters = 0; virLogFiltersSerial++; @@ -371,9 +394,10 @@ * Removes the set of logging output defined. */ static void -virLogResetOutputs(void) +virLogResetOutputs(bool freemem) { - virLogOutputListFree(virLogOutputs, virLogNbOutputs); + if (freemem) + virLogOutputListFree(virLogOutputs, virLogNbOutputs); virLogOutputs = NULL; virLogNbOutputs = 0; } @@ -1379,7 +1403,7 @@ return -1; virLogLock(); - virLogResetOutputs(); + virLogResetOutputs(true); #if WITH_SYSLOG_H /* syslog needs to be special-cased, since it keeps the fd in private */ @@ -1422,7 +1446,7 @@ return -1; virLogLock(); - virLogResetFilters(); + virLogResetFilters(true); virLogFilters = filters; virLogNbFilters = nfilters; virLogUnlock();