splice_cat can leave open file descriptors around. This breaks the
valgrind testsuite with --track-fds=yes. This is fairly innocent, like
still reachable memory, but does need a new suppression when tracking
file descriptor handling. Introduce a new splice_cat_close function
that can be used on error from splice_cat and before exiting main.
* src/cat.c (splice_cat): Move static pipefd and pipefd_pipe_size to
file level, guarded by HAVE_SPLICE. Move pipefd close and cleanup from
error handler to...
(splice_cat_close): New function. Empty if we don't HAVE_SPLICE.
(main): Call splice_cat_close before exit.
---
src/cat.c | 47 +++++++++++++++++++++++++++++++++++------------
1 file changed, 35 insertions(+), 12 deletions(-)
diff --git a/src/cat.c b/src/cat.c
index 43063fb9b27e..33ef4db9cdc7 100644
--- a/src/cat.c
+++ b/src/cat.c
@@ -549,6 +549,38 @@ copy_cat (void)
}
}
+#if HAVE_SPLICE
+
+/* If PIPEFD[0] is a non-negative value, we have an open pipe from a
+ previous call to splice_cat. At the start of splice_cat the pipe
+ will always be empty. Use splice_cat_close on error or end of
+ program. */
+static int pipefd[2] = { -1, -1 };
+
+/* The size of the pipe referred to by PIPEFD. */
+static idx_t pipefd_pipe_size = 0;
+
+/* Close PIDEFD[0] and PIPEFD[1] if not -1, reset pipefd_pipe_size. */
+static void
+splice_cat_close (void)
+{
+ if (pipefd[0] >= 0)
+ {
+ close (pipefd[0]);
+ close (pipefd[1]);
+ }
+
+ pipefd[0] = pipefd[1] = -1;
+ pipefd_pipe_size = 0;
+}
+
+#else
+
+/* No splice no close. */
+static void splice_cat_close (void) { }
+
+#endif
+
/* Copy data from input to output using splice if possible.
Return 1 if successful, 0 if ordinary read+write should be tried,
-1 if a serious problem has been diagnosed. */
@@ -562,14 +594,6 @@ splice_cat (void)
#if HAVE_SPLICE
- /* If PIPEFD[0] is a non-negative value, we have an open pipe from a
- previous call to this function. At the start of this function the
- pipe will always be empty. */
- static int pipefd[2] = { -1, -1 };
-
- /* The size of the pipe referred to by PIPEFD. */
- static idx_t pipefd_pipe_size = 0;
-
/* Create an intermediate pipe if it is not already open.
Even if both input and output are pipes,
so that read and write errors can be distinguished. */
@@ -645,11 +669,8 @@ splice_cat (void)
{
/* Recreate the pipe on internal error. */
int saved_errno = errno;
- close (pipefd[0]);
- close (pipefd[1]);
+ splice_cat_close ();
errno = saved_errno;
- pipefd[0] = pipefd[1] = -1;
- pipefd_pipe_size = 0;
error (0, errno, "%s", _("splice error"));
}
else if (! in_ok)
@@ -968,6 +989,8 @@ main (int argc, char **argv)
alignfree (inbuf);
#endif
+ splice_cat_close ();
+
if (have_read_stdin && close (STDIN_FILENO) < 0)
error (EXIT_FAILURE, errno, _("closing standard input"));
--
2.56.0