Message ID | 20240627162005.407679-1-mcermak@redhat.com |
---|---|
State | New |
Headers | show |
Series | misc: Add new test for daemon | expand |
On 27/06/24 13:20, Martin Cermak wrote: > This commit adds a new testcase for the daemon function. > --- > The dev_null_redir function may be too linux specific. Not sure about > a better way to do it. This new tests has failed for some reason on aarch64/armhf buildbot [1][2]. The log does not show much information though [2] FAIL: misc/tst-daemon original exit status 127 Usually '127' means a SEGFAULT. [1] https://patchwork.sourceware.org/project/glibc/patch/20240627162005.407679-1-mcermak@redhat.com/ [2] https://ci.linaro.org/job/tcwg_glibc_check--master-aarch64-precommit/2000/artifact/artifacts/artifacts.precommit/00-sumfiles/ > --- > misc/Makefile | 1 + > misc/tst-daemon.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 156 insertions(+) > create mode 100644 misc/tst-daemon.c > > diff --git a/misc/Makefile b/misc/Makefile > index c273ec6974..7313f9122d 100644 > --- a/misc/Makefile > +++ b/misc/Makefile > @@ -232,6 +232,7 @@ gpl2lgpl := \ > tests := \ > bug-hsearch1 \ > bug18240 \ > + tst-daemon \ > tst-dbl-efgcvt \ > tst-dirname \ > tst-empty \ > diff --git a/misc/tst-daemon.c b/misc/tst-daemon.c > new file mode 100644 > index 0000000000..9ab72781e1 > --- /dev/null > +++ b/misc/tst-daemon.c > @@ -0,0 +1,155 @@ > +/* Tests for daemon. > + Copyright (C) 2024 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#include <errno.h> > +#include <error.h> > +#include <stdlib.h> > +#include <wait.h> > +#include <support/check.h> > +#include <string.h> > +#include <stdio.h> > + > +/* Define pipe communication encoding. */ > +#define STATUS_PASS 'p' > +#define STATUS_FAIL 'f' > + > +/* Check if given file descriptor is redirected to /dev/null. */ > +unsigned char > +dev_null_redir (FILE * f) > +{ > + char b1[1024]; > + char b2[1024]; > + ssize_t len; > + > + int fd = fileno (f); > + > + len = snprintf (b1, sizeof (b1), "/proc/self/fd/%d", fd); > + if (len < 0 || len >= sizeof (b1)) > + return 1; > + > + len = readlink (b1, b2, sizeof (b2) - 1); > + if (len < 0) > + return 1; > + > + b2[len] = '\0'; > + > + if (strcmp (b2, "/dev/null") != 0) > + return 1; > + > + return 0; > +} > + > +/* Run one daemon test with specified parameters. */ > +void > +test_daemon (int nochdir, int noclose) > +{ > + pid_t pid; > + int status; > + int pipefd[2]; > + char buf; > + > + if (pipe (pipefd) == -1) > + error (EXIT_FAILURE, errno, "failed to create the pipe"); > + > + pid = fork (); > + if (pid == 0) > + { > + /* This is the child. */ > + char cwd[1024]; > + char origcwd[1024]; > + char retval = STATUS_PASS; > + > + getcwd (origcwd, sizeof (origcwd)); > + > + /* Daemonize the child. */ > + if (daemon (nochdir, noclose) != 0) > + retval = STATUS_FAIL; > + > + switch (nochdir) > + { > + case 0: > + getcwd (cwd, sizeof (cwd)); > + if (strcmp (cwd, "/") != 0) > + retval = STATUS_FAIL; > + break; > + default: > + getcwd (cwd, sizeof (cwd)); > + if (strcmp (cwd, origcwd) != 0) > + retval = STATUS_FAIL; > + } > + > + switch (noclose) > + { > + case 0: > + if (dev_null_redir (stdin) != 0) > + retval = STATUS_FAIL; > + if (dev_null_redir (stdout) != 0) > + retval = STATUS_FAIL; > + if (dev_null_redir (stderr) != 0) > + retval = STATUS_FAIL; > + break; > + default: > + if (dev_null_redir (stdin) != 1) > + retval = STATUS_FAIL; > + if (dev_null_redir (stdout) != 1) > + retval = STATUS_FAIL; > + if (dev_null_redir (stderr) != 1) > + retval = STATUS_FAIL; > + } > + > + /* Report test result to the parent. */ > + close (pipefd[0]); > + write (pipefd[1], &retval, 1); > + close (pipefd[1]); > + > + _exit (0); > + } > + else if (pid < 0) > + /* Something went wrong. */ > + error (EXIT_FAILURE, errno, "cannot fork"); > + > + /* This is the parent. */ > + if (waitpid (pid, &status, 0) != pid) > + error (EXIT_FAILURE, 0, "oops, wrong test program terminated"); > + > + if (WTERMSIG (status) != 0) > + error (EXIT_FAILURE, 0, "child terminated incorrectly"); > + status = WEXITSTATUS (status); > + > + /* Read test result from the daemon and report it. */ > + close (pipefd[1]); > + if (read (pipefd[0], &buf, 1) != 1) > + error (EXIT_FAILURE, 0, "failed reading daemon status"); > + close (pipefd[0]); > + TEST_VERIFY_EXIT (buf == STATUS_PASS); > +} > + > + > +int > +do_test (void) > +{ > + /* Run daemon tests with various parameters. */ > + test_daemon (0, 0); > + test_daemon (1, 0); > + test_daemon (0, 1); > + test_daemon (1, 1); > + > + return 0; > +} > + > +#include <support/test-driver.c>
diff --git a/misc/Makefile b/misc/Makefile index c273ec6974..7313f9122d 100644 --- a/misc/Makefile +++ b/misc/Makefile @@ -232,6 +232,7 @@ gpl2lgpl := \ tests := \ bug-hsearch1 \ bug18240 \ + tst-daemon \ tst-dbl-efgcvt \ tst-dirname \ tst-empty \ diff --git a/misc/tst-daemon.c b/misc/tst-daemon.c new file mode 100644 index 0000000000..9ab72781e1 --- /dev/null +++ b/misc/tst-daemon.c @@ -0,0 +1,155 @@ +/* Tests for daemon. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <error.h> +#include <stdlib.h> +#include <wait.h> +#include <support/check.h> +#include <string.h> +#include <stdio.h> + +/* Define pipe communication encoding. */ +#define STATUS_PASS 'p' +#define STATUS_FAIL 'f' + +/* Check if given file descriptor is redirected to /dev/null. */ +unsigned char +dev_null_redir (FILE * f) +{ + char b1[1024]; + char b2[1024]; + ssize_t len; + + int fd = fileno (f); + + len = snprintf (b1, sizeof (b1), "/proc/self/fd/%d", fd); + if (len < 0 || len >= sizeof (b1)) + return 1; + + len = readlink (b1, b2, sizeof (b2) - 1); + if (len < 0) + return 1; + + b2[len] = '\0'; + + if (strcmp (b2, "/dev/null") != 0) + return 1; + + return 0; +} + +/* Run one daemon test with specified parameters. */ +void +test_daemon (int nochdir, int noclose) +{ + pid_t pid; + int status; + int pipefd[2]; + char buf; + + if (pipe (pipefd) == -1) + error (EXIT_FAILURE, errno, "failed to create the pipe"); + + pid = fork (); + if (pid == 0) + { + /* This is the child. */ + char cwd[1024]; + char origcwd[1024]; + char retval = STATUS_PASS; + + getcwd (origcwd, sizeof (origcwd)); + + /* Daemonize the child. */ + if (daemon (nochdir, noclose) != 0) + retval = STATUS_FAIL; + + switch (nochdir) + { + case 0: + getcwd (cwd, sizeof (cwd)); + if (strcmp (cwd, "/") != 0) + retval = STATUS_FAIL; + break; + default: + getcwd (cwd, sizeof (cwd)); + if (strcmp (cwd, origcwd) != 0) + retval = STATUS_FAIL; + } + + switch (noclose) + { + case 0: + if (dev_null_redir (stdin) != 0) + retval = STATUS_FAIL; + if (dev_null_redir (stdout) != 0) + retval = STATUS_FAIL; + if (dev_null_redir (stderr) != 0) + retval = STATUS_FAIL; + break; + default: + if (dev_null_redir (stdin) != 1) + retval = STATUS_FAIL; + if (dev_null_redir (stdout) != 1) + retval = STATUS_FAIL; + if (dev_null_redir (stderr) != 1) + retval = STATUS_FAIL; + } + + /* Report test result to the parent. */ + close (pipefd[0]); + write (pipefd[1], &retval, 1); + close (pipefd[1]); + + _exit (0); + } + else if (pid < 0) + /* Something went wrong. */ + error (EXIT_FAILURE, errno, "cannot fork"); + + /* This is the parent. */ + if (waitpid (pid, &status, 0) != pid) + error (EXIT_FAILURE, 0, "oops, wrong test program terminated"); + + if (WTERMSIG (status) != 0) + error (EXIT_FAILURE, 0, "child terminated incorrectly"); + status = WEXITSTATUS (status); + + /* Read test result from the daemon and report it. */ + close (pipefd[1]); + if (read (pipefd[0], &buf, 1) != 1) + error (EXIT_FAILURE, 0, "failed reading daemon status"); + close (pipefd[0]); + TEST_VERIFY_EXIT (buf == STATUS_PASS); +} + + +int +do_test (void) +{ + /* Run daemon tests with various parameters. */ + test_daemon (0, 0); + test_daemon (1, 0); + test_daemon (0, 1); + test_daemon (1, 1); + + return 0; +} + +#include <support/test-driver.c>