virtlogd 6.9.0, 6.8.0 crashes when starting a domain when built with glibc, libtirpc and LTO
Description
I am updating the libvirt
package for Void Linux from 6.6.0 to 6.9.0. Void supports several architectures as well as glibc
and musl
C libraries. When building for x86_64
with glibc
with Void's default build options---specifically, -Db_lto=true
, the resulting virtlogd
executable will crash whenever a libvirt
domain is started. When building for x86_64
with musl
, virtlogd
behaves as expected. The stack trace (see below) on glibc
suggests that the symbol xdr_uint64_t
is resolved from glibc
rather than libtirpc
. Because musl
does not provide xdr_uint64_t
, the symbol is correctly resolved from libtirpc
in that case. Disabling LTO by adding a -Db_lto=true
causes virtlogd
to behave as expected on glibc
.
I have confirmed that this issue affects releases 6.9.0 and 6.8.0.
To Reproduce
The build process in Void uses a standardized meson
build style. The portion relevant for this issue is the do_configure
function. The actual build and installation are described in the do_build
and do_install
functions defined in the same file. The function do_check
is not important and do_patch
is only relevant for cross compilation, which is not the case here.
Specifics of the libvirt
build are described in the template which defines the dependencies (hostmakedepends
and makedepends
are relevant here and, for native builds as described in this issue, are effectively merged into a single list of dependencies present for the build procedure). The configure_args
referenced from the do_configure
function in the build style are defined as configure_args
in the template.
From this, the libvirt
package can be configured (from the source directory with an empty build
subdirectory) with
meson --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/libexec \
--bindir=/usr/bin --sbindir=/usr/bin --includedir=/usr/include \
--datadir=/usr/share --mandir=/usr/share/man --infodir=/usr/share/info \
--localdir=/usr/share/local --sysconfdir=/etc --localstatedir=/var \
--sharedstatedir=/var/lib --buildtype=plain --auto-features=auto \
--wrap-mode=nodownload -Db_lto=true -Db_ndebug=true -D_staticpic=true \
-Dqemu_user=libvirt -Dqemu_group=libvirt -Drunstatedir=/run . build
and built and installed with the usual make -C build all; make -C build install
. Most of these flags are almost certainly irrelevant for this issue.
Observed behavior
If configured and built as above, attempting to start a domain with virsh start <domain>
will fail with the error
error: Failed to start domain <domain>
error: can't connect to virtlogd: End of file while reading data: Input/output error
If virtlogd
is started in a debugger before attempting to start a domain, the nature of the error becomes clear in a backtrace:
Thread 1 "virtlogd" received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) bt
#0 0x0000000000000000 in ?? ()
#1 0x00007ffff7f2168b in __GI_xdr_uint64_t (xdrs=xdrs@entry=0x7fffffffded0,
uip=uip@entry=0x5555555c4320) at xdr_intXX_t.c:72
#2 0x0000555555561271 in xdr_virLogManagerProtocolLogFilePosition (xdrs=0x7fffffffded0,
objp=0x5555555c4320) at src/logging/log_protocol.c:53
#3 0x0000555555561309 in xdr_virLogManagerProtocolDomainOpenLogFileRet (
xdrs=<optimized out>, objp=<optimized out>) at src/logging/log_protocol.c:88
#4 0x00007ffff7b979fb in virNetMessageEncodePayload (msg=0x5555555c2950,
filter=0x555555561300 <xdr_virLogManagerProtocolDomainOpenLogFileRet>,
data=0x5555555c4320) at ../src/rpc/virnetmessage.c:360
#5 0x00007ffff7b84bfe in virNetServerProgramDispatchCall (msg=0x5555555c2950,
client=0x5555555c3020, server=<optimized out>, prog=0x5555555c2010)
at ../src/rpc/virnetserverprogram.c:474
#6 virNetServerProgramDispatch (prog=0x5555555c2010, server=<optimized out>,
client=0x5555555c3020, msg=0x5555555c2950) at ../src/rpc/virnetserverprogram.c:302
#7 0x00007ffff7b84f36 in virNetServerProcessMsg (msg=0x5555555c2950,
prog=0x5555555c2010, client=0x5555555c3020, srv=0x5555555bd080)
at ../src/rpc/virnetserver.c:137
#8 virNetServerDispatchNewMessage (client=0x5555555c3020, msg=0x5555555c2950,
opaque=0x5555555bd080) at ../src/rpc/virnetserver.c:231
#9 0x00007ffff7c8fed9 in virEventGLibHandleDispatch (fd=<optimized out>,
condition=<optimized out>, opaque=0x5555555c4000) at ../src/util/vireventglib.c:120
#10 0x00007ffff790c0fe in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
#11 0x00007ffff790dd90 in ?? () from /usr/lib/libglib-2.0.so.0
#12 0x00007ffff790ddcf in g_main_context_iteration () from /usr/lib/libglib-2.0.so.0
#13 0x00007ffff7c8e530 in virEventGLibRunOnce () at ../src/util/vireventglib.c:533
#14 0x00007ffff7b7f3ad in virNetDaemonRun (dmn=0x5555555a7820)
at ../src/rpc/virnetdaemon.c:862
#15 0x000055555555ba16 in main (argc=<optimized out>, argv=0x7fffffffe4e8)
at ../src/logging/log_daemon.c:943
Note that __GI_xdr_uint64_t
in frame #1
, defined at xdr_intXX_t.c:72
, corresponds to the definition in glibc
(in this case, version 2.30), rather than the definition in libtirpc
.
Expected behavior
virtlogd
should not crash, and the domain should launch successfully.
Workaround
Adding the argument -Db_lto=false
to the meson
command line during configuration, after the initial -Db_lto=true
(or, equivalently, replacing the -Db_lto=true
with -Db_lto=false
) causes virtlogd
to run successfully when a domain is started.