tools/libxs: Fix CLOEXEC handling in xs_fileno()

xs_fileno() opens a pipe on first use to communicate between the watch thread
and the main thread.  Nothing ever sets CLOEXEC on the file descriptors.

Check for the availability of the pipe2() function with configure.  Despite
starting life as Linux-only, FreeBSD and NetBSD have gained it.

When pipe2() isn't available, try our best with pipe() and set_cloexec().

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
This commit is contained in:
Andrew Cooper committed 2024-07-02 10:52:59 +01:00
1 parent 1957dd6aff
commit a2ff677852
4 files changed
+32 -1

No files matched your search

+3
View File
@@ -39,6 +39,9 @@
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `pipe2' function. */
#undef HAVE_PIPE2
/* pygrub enabled */
#undef HAVE_PYGRUB
+12
View File
@@ -9751,6 +9751,18 @@ if test "$ax_found" = "0"; then :
fi
for ac_func in pipe2
do :
ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
if test "x$ac_cv_func_pipe2" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_PIPE2 1
_ACEOF
fi
done
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
+2
View File
@@ -543,4 +543,6 @@ AS_IF([test "x$pvshim" = "xy"], [
AX_FIND_HEADER([INCLUDE_ENDIAN_H], [endian.h sys/endian.h])
AC_CHECK_FUNCS([pipe2])
AC_OUTPUT()
+15 -1
View File
@@ -190,13 +190,27 @@ static bool set_cloexec(int fd)
return fcntl(fd, flags | FD_CLOEXEC) >= 0;
}
static int pipe_cloexec(int fds[2])
{
#if HAVE_PIPE2
return pipe2(fds, O_CLOEXEC);
#else
if (pipe(fds) < 0)
return -1;
/* Best effort to set CLOEXEC. Racy. */
set_cloexec(fds[0]);
set_cloexec(fds[1]);
return 0;
#endif
}
int xs_fileno(struct xs_handle *h)
{
char c = 0;
mutex_lock(&h->watch_mutex);
if ((h->watch_pipe[0] == -1) && (pipe(h->watch_pipe) != -1)) {
if ((h->watch_pipe[0] == -1) && (pipe_cloexec(h->watch_pipe) != -1)) {
/* Kick things off if the watch list is already non-empty. */
if (!XEN_TAILQ_EMPTY(&h->watch_list))
while (write(h->watch_pipe[1], &c, 1) != 1)
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.