tests: Call openpty (if available) without using dlsym

The SONAME of libutil varies between architectures, so the logic to find
the SONAME of libutil was only correct for native builds (Linux on
Linux), not for cross-builds. The regular expression was also not
sufficiently broad to match the SONAME used on the alpha architecture,
which is apparently libutil.so.1.1.

Instead of screen-scraping the output of ldconfig and using that to
dlopen the library that contains openpty, it seems more reliable to
emit a link-time reference to openpty and let the linker do its job.
It's also less code.

Bug-Debian: https://bugs.debian.org/1007946
Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
Simon McVittie 2022-03-19 11:16:46 +00:00
parent c5e12d9577
commit 1726e150f4
2 changed files with 28 additions and 36 deletions

View File

@ -12,20 +12,20 @@ test_c_args = [
'-UG_DISABLE_ASSERT',
]
# workaround for https://github.com/mesonbuild/meson/issues/6880
if build_machine.system() == 'linux'
libutil_name = 'libutil'
libutil = run_command('sh', '-c',
'''ldconfig -p | grep -o "[[:space:]]@0@\.so\(\.[0-9]\+\)\?\b"'''
.format(libutil_name), check: false).stdout().strip().split('\n')
libutil_dep = dependency('', required : false)
if libutil.length() > 0
message('Found libutil as @0@'.format(libutil[0]))
test_c_args += '-DLIBUTIL_SONAME="@0@"'.format(libutil[0])
else
warning('libutil not found')
endif # libutil.length() > 0
endif # build_machine.system() == 'linux'
if cc.has_header('pty.h')
have_openpty = cc.has_function('openpty', prefix : '#include <pty.h>')
if host_machine.system() == 'linux' and not have_openpty
libutil_dep = cc.find_library('util', required : false)
have_openpty = cc.has_function('openpty', dependencies : libutil_dep, prefix : '#include <pty.h>')
endif
if have_openpty
test_c_args += '-DHAVE_OPENPTY'
endif
endif
if host_machine.system() == 'windows'
common_gio_tests_deps += [iphlpapi_dep, winsock2, cc.find_library ('secur32')]
@ -91,7 +91,7 @@ gio_tests = {
'network-monitor' : {},
'network-monitor-race' : {},
'permission' : {},
'pollable' : {'dependencies' : [libdl_dep]},
'pollable' : {'dependencies' : [libutil_dep]},
'power-profile-monitor' : {},
'proxy-test' : {},
'readwrite' : {},

View File

@ -22,12 +22,20 @@
#include <glib/gstdio.h>
#ifdef G_OS_UNIX
#include <dlfcn.h>
#include <fcntl.h>
#ifdef HAVE_OPENPTY
#include <pty.h>
#endif
#include <gio/gunixinputstream.h>
#include <gio/gunixoutputstream.h>
#endif
/* openpty() is non-standard and might not be available on all kernels
* and libc implementations, but glibc on Linux definitely has it */
#if defined(__linux__) && defined(__GNUC__) && !defined(HAVE_OPENPTY)
#error Should have been able to find openpty on GNU/Linux
#endif
GMainLoop *loop;
GPollableInputStream *in;
GOutputStream *out;
@ -185,31 +193,19 @@ test_pollable_unix_pipe (void)
static void
test_pollable_unix_pty (void)
{
int (*openpty_impl) (int *, int *, char *, void *, void *);
#ifdef HAVE_OPENPTY
int a, b, status;
#ifdef LIBUTIL_SONAME
void *handle;
#endif
g_test_summary ("Test that PTYs are considered pollable");
#ifdef LIBUTIL_SONAME
handle = dlopen (LIBUTIL_SONAME, RTLD_GLOBAL | RTLD_LAZY);
g_assert_nonnull (handle);
#endif
#ifdef HAVE_OPENPTY
status = openpty (&a, &b, NULL, NULL, NULL);
openpty_impl = dlsym (RTLD_DEFAULT, "openpty");
if (openpty_impl == NULL)
{
g_test_skip ("System does not support openpty()");
goto close_libutil;
}
status = openpty_impl (&a, &b, NULL, NULL, NULL);
if (status == -1)
{
g_test_skip ("Unable to open PTY");
goto close_libutil;
return;
}
in = G_POLLABLE_INPUT_STREAM (g_unix_input_stream_new (a, TRUE));
@ -222,12 +218,8 @@ test_pollable_unix_pty (void)
close (a);
close (b);
close_libutil:
#ifdef LIBUTIL_SONAME
dlclose (handle);
#else
return;
g_test_skip ("openpty not found");
#endif
}