void-packages/srcpkgs/libvirt/files/musl-fork-nofree.patch
Andrew J. Hesford e17f291d75 libvirt: fix deadlocks with musl
Alpine Linux includes two patches to fix deadlocks with musl. Because
upstream is not interested in merging these patches, conditionally apply
one only for musl archs. The other is guarded by conditional compilation
directives, so there is no harm in applying the patch unconditionally.

Closes #25905.
2021-01-01 22:21:23 -05:00

138 lines
3.8 KiB
Diff

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 <ncopa alpinelinux org>
---
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.c src/util/virlog.c
--- src/util/virlog.c
+++ src/util/virlog.c
@@ -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(virLogSourcePtr 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();
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,