summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEnji Cooper <ngie@FreeBSD.org>2026-09-21 02:29:32 +0000
committerEnji Cooper <ngie@FreeBSD.org>2026-09-21 02:29:32 +0000
commitf6ae5b18a6ed3fd628c48723e608fa3a9f5b1906 (patch)
treeba23129aaf87f9b2a1ea30d573f114a1b499caf4
parent5cb96993447fc7bd26aba808fd6961652effa4bc (diff)
kyua: import kyua-0.15.0-rc1vendor/kyua/kyua-0.15.0-rc1vendor/kyua
This change adds kyua kyua-0.15.0-rc1 from [upstream][1]. The kyua-0.15.0-rc1 artifact was been verified by [SHA256 checksum][3]. This release incorporates items upstreamed from FreeBSD src and uses C++ attributes (`[[maybe_unused]]` and `[[noreturn]]`) instead of ad hoc equivalents. More information about the release (from a high level) can be found in the [release notes][4]. Updated via [`update_kyua.sh`][4] `update_kyua.sh 0.15.0-rc1 kyua-0.15.0`. 1: https://github.com/freebsd/kyua/releases/download/kyua-0.15.0-rc1/kyua-0.15.0-rc1.tar.gz 2: https://github.com/freebsd/kyua/releases/download/kyua-0.15.0-rc1/kyua-0.15.0-rc1.tar.gz.sha256 3: https://github.com/freebsd/kyua/blob/kyua-0.15.0-rc1/NEWS.md 4: https://codeberg.org/ngie/freebsd-powertools:shell/update_kyua.sh@10a04edb
-rw-r--r--Doxyfile.in1
-rw-r--r--Makefile.in2
-rw-r--r--cli/cmd_debug.cpp83
-rwxr-xr-xconfigure194
-rw-r--r--configure.ac2
-rw-r--r--doc/kyuafile.5.in2
-rw-r--r--engine/atf.hpp21
-rw-r--r--engine/debugger.hpp7
-rw-r--r--engine/execenv/execenv.hpp2
-rw-r--r--engine/execenv/execenv_host.hpp2
-rw-r--r--engine/googletest.cpp1
-rw-r--r--engine/googletest.hpp13
-rw-r--r--engine/plain.hpp13
-rw-r--r--engine/scheduler.cpp7
-rw-r--r--engine/scheduler.hpp26
-rw-r--r--engine/scheduler_test.cpp24
-rw-r--r--engine/tap.hpp13
-rw-r--r--m4/compiler-features.m464
-rw-r--r--os/freebsd/execenv_jail.hpp2
-rw-r--r--os/freebsd/execenv_jail_stub.cpp2
-rw-r--r--os/freebsd/reqs_checker_kmods.cpp2
-rw-r--r--os/freebsd/utils/jail.hpp7
-rw-r--r--utils/cmdline/options.cpp20
-rw-r--r--utils/cmdline/options.hpp8
-rw-r--r--utils/cmdline/parser.cpp20
-rw-r--r--utils/defs.hpp.in10
-rw-r--r--utils/fs/operations.cpp2
-rw-r--r--utils/process/child.cpp24
-rw-r--r--utils/process/child.hpp9
-rw-r--r--utils/process/child.ipp20
-rw-r--r--utils/process/executor_test.cpp23
-rw-r--r--utils/process/isolation.cpp2
-rw-r--r--utils/process/operations.hpp6
-rw-r--r--utils/process/operations_test.cpp4
-rw-r--r--utils/sanity.hpp4
-rw-r--r--utils/signals/misc_test.cpp2
-rw-r--r--utils/sqlite/test_utils.hpp4
-rw-r--r--utils/stacktrace.cpp2
-rw-r--r--utils/stacktrace_test.cpp9
-rw-r--r--utils/test_utils.ipp2
-rw-r--r--utils/text/regex.cpp4
41 files changed, 325 insertions, 340 deletions
diff --git a/Doxyfile.in b/Doxyfile.in
index e28d82f8999a..ac1dbf3398b6 100644
--- a/Doxyfile.in
+++ b/Doxyfile.in
@@ -45,7 +45,6 @@ JAVADOC_AUTOBRIEF = YES
MACRO_EXPANSION = YES
OUTPUT_DIRECTORY = @top_builddir@/api-docs
OUTPUT_LANGUAGE = English
-PREDEFINED += "KYUA_DEFS_NORETURN="
PREDEFINED += "KYUA_DEFS_FORMAT_PRINTF(x, y)="
PROJECT_NAME = "@PACKAGE_NAME@"
PROJECT_NUMBER = @VERSION@
diff --git a/Makefile.in b/Makefile.in
index cb8356fe8380..2dad43957ea9 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -3229,9 +3229,7 @@ AR = @AR@
ATF_CXX_CFLAGS = @ATF_CXX_CFLAGS@
ATF_CXX_LIBS = @ATF_CXX_LIBS@
ATF_SH = @ATF_SH@
-ATTRIBUTE_NORETURN = @ATTRIBUTE_NORETURN@
ATTRIBUTE_PURE = @ATTRIBUTE_PURE@
-ATTRIBUTE_UNUSED = @ATTRIBUTE_UNUSED@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
diff --git a/cli/cmd_debug.cpp b/cli/cmd_debug.cpp
index fdf37abfedc7..f5e48572407e 100644
--- a/cli/cmd_debug.cpp
+++ b/cli/cmd_debug.cpp
@@ -28,7 +28,12 @@
#include "cli/cmd_debug.hpp"
+extern "C" {
+#include <unistd.h>
+}
+
#include <cstdlib>
+#include <cstring>
#include <iostream>
#include "cli/common.ipp"
@@ -39,13 +44,20 @@
#include "utils/cmdline/parser.ipp"
#include "utils/cmdline/ui.hpp"
#include "utils/format/macros.hpp"
+#include "utils/fs/path.hpp"
+#include "utils/process/child.ipp"
#include "utils/process/executor.hpp"
+#include "utils/process/operations.hpp"
+#include "utils/process/status.hpp"
namespace cmdline = utils::cmdline;
namespace config = utils::config;
namespace executor = utils::process::executor;
+namespace process = utils::process;
using cli::cmd_debug;
+using utils::process::args_vector;
+using utils::process::child;
namespace {
@@ -63,6 +75,57 @@ const cmdline::bool_option pause_before_cleanup_option(
"Pauses right before the test cleanup");
+static const char* DEFAULT_CMD = "$SHELL";
+const cmdline::string_option execute_option(
+ 'x', "execute",
+ "A command to run within the given execenv upon test failure",
+ "cmd", DEFAULT_CMD, true);
+
+
+/// Functor to execute a program.
+class execute {
+ const std::string& _cmd;
+ executor::exit_handle& _eh;
+
+public:
+ /// Constructor.
+ ///
+ /// \param program Program binary absolute path.
+ /// \param args Program arguments.
+ execute(
+ const std::string& cmd_,
+ executor::exit_handle& eh_) :
+ _cmd(cmd_),
+ _eh(eh_)
+ {
+ }
+
+ /// Body of the subprocess.
+ void
+ operator()(void)
+ {
+ if (::chdir(_eh.work_directory().c_str()) == -1) {
+ std::cerr << "execute: chdir() errors: "
+ << std::strerror(errno) << ".\n";
+ std::exit(EXIT_FAILURE);
+ }
+
+ std::string program_path = "/bin/sh";
+ const char* shell = std::getenv("SHELL");
+ if (shell)
+ program_path = shell;
+
+ args_vector av;
+ if (!(_cmd.empty() || _cmd == DEFAULT_CMD)) {
+ av.push_back("-c");
+ av.push_back(_cmd);
+ }
+
+ process::exec(utils::fs::path(program_path), av);
+ }
+};
+
+
/// The debugger interface implementation.
class dbg : public engine::debugger {
/// Object to interact with the I/O of the program.
@@ -104,6 +167,21 @@ public:
}
};
+ void upon_test_failure(
+ const model::test_program_ptr&,
+ const model::test_case&,
+ optional< model::test_result >&,
+ executor::exit_handle& eh) const
+ {
+ if (!_cmdline.has_option(execute_option.long_name()))
+ return;
+ const std::string& cmd = _cmdline.get_option<cmdline::string_option>(
+ execute_option.long_name());
+ std::unique_ptr< process::child > child = child::fork_interactive(
+ execute(cmd, eh));
+ (void) child->wait();
+ };
+
};
@@ -128,6 +206,8 @@ cmd_debug::cmd_debug(void) : cli_command(
add_option(cmdline::path_option(
"stderr", "Where to direct the standard error of the test case",
"path", "/dev/stderr"));
+
+ add_option(execute_option);
}
@@ -152,7 +232,8 @@ cmd_debug::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline,
engine::debugger_ptr debugger = nullptr;
if (cmdline.has_option(pause_before_cleanup_upon_fail_option.long_name())
- || cmdline.has_option(pause_before_cleanup_option.long_name())) {
+ || cmdline.has_option(pause_before_cleanup_option.long_name())
+ || cmdline.has_option(execute_option.long_name())) {
debugger = std::shared_ptr< engine::debugger >(new dbg(ui, cmdline));
}
diff --git a/configure b/configure
index c60596311d2b..c0add152ddc6 100755
--- a/configure
+++ b/configure
@@ -711,9 +711,7 @@ build_cpu
build
LIBTOOL
UMOUNT
-ATTRIBUTE_UNUSED
ATTRIBUTE_PURE
-ATTRIBUTE_NORETURN
HAVE_CXX20
ac_ct_AR
AR
@@ -1823,50 +1821,6 @@ fi
} # ac_fn_cxx_try_link
-# ac_fn_c_try_run LINENO
-# ----------------------
-# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
-# executables *can* be run.
-ac_fn_c_try_run ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { { ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-printf '%s\n' "$ac_try_echo"; } >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- printf '%s\n' "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
- { { case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-printf '%s\n' "$ac_try_echo"; } >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- printf '%s\n' "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }
-then :
- ac_retval=0
-else case e in #(
- e) printf '%s\n' "$as_me: program exited with status $ac_status" >&5
- printf '%s\n' "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=$ac_status ;;
-esac
-fi
- rm -rf conftest.dSYM conftest_ipa8_conftest.oo
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_run
-
# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists and can be compiled using the include files in
@@ -2014,6 +1968,50 @@ printf '%s\n' "$ac_res" >&6; }
} # ac_fn_c_check_func
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
+# executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf '%s\n' "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ printf '%s\n' "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf '%s\n' "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ printf '%s\n' "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+then :
+ ac_retval=0
+else case e in #(
+ e) printf '%s\n' "$as_me: program exited with status $ac_status" >&5
+ printf '%s\n' "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status ;;
+esac
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
# ac_fn_cxx_try_cpp LINENO
# ------------------------
# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
@@ -7229,63 +7227,6 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
- { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking whether __attribute__((noreturn)) is supported" >&5
-printf %s "checking whether __attribute__((noreturn)) is supported... " >&6; }
-if test ${kyua_cv_attribute_noreturn+y}
-then :
- printf %s "(cached) " >&6
-else case e in #(
- e)
- if test "$cross_compiling" = yes
-then :
- { { printf '%s\n' "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
-printf '%s\n' "$as_me: error: in '$ac_pwd':" >&2;}
-as_fn_error $? "cannot run test program while cross compiling
-See 'config.log' for more details" "$LINENO" 5; }
-else case e in #(
- e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main (void)
-{
-
-#if ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
- return 0;
-#else
- return 1;
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"
-then :
- kyua_cv_attribute_noreturn=yes
-else case e in #(
- e) kyua_cv_attribute_noreturn=no ;;
-esac
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
-esac
-fi
-
- ;;
-esac
-fi
-{ printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $kyua_cv_attribute_noreturn" >&5
-printf '%s\n' "$kyua_cv_attribute_noreturn" >&6; }
- if test "${kyua_cv_attribute_noreturn}" = yes; then
- attribute_value="__attribute__((noreturn))"
- else
- attribute_value=""
- fi
- ATTRIBUTE_NORETURN=${attribute_value}
-
-
-
{ printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking whether __attribute__((__pure__)) is supported" >&5
printf %s "checking whether __attribute__((__pure__)) is supported... " >&6; }
if test ${kyua_cv_attribute_pure+y}
@@ -7334,53 +7275,6 @@ printf '%s\n' "$kyua_cv_attribute_pure" >&6; }
ATTRIBUTE_PURE=${attribute_value}
-
- { printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking whether __attribute__((__unused__)) is supported" >&5
-printf %s "checking whether __attribute__((__unused__)) is supported... " >&6; }
-if test ${kyua_cv_attribute_unused+y}
-then :
- printf %s "(cached) " >&6
-else case e in #(
- e)
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-static void
-function(int a __attribute__((__unused__)))
-{
-}
-int
-main (void)
-{
-
- function(3);
- return 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"
-then :
- kyua_cv_attribute_unused=yes
-else case e in #(
- e) kyua_cv_attribute_unused=no ;;
-esac
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
- ;;
-esac
-fi
-{ printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $kyua_cv_attribute_unused" >&5
-printf '%s\n' "$kyua_cv_attribute_unused" >&6; }
- if test "${kyua_cv_attribute_unused}" = yes; then
- attribute_value="__attribute__((__unused__))"
- else
- attribute_value=""
- fi
- ATTRIBUTE_UNUSED=${attribute_value}
-
-
ac_header= ac_cache=
for ac_item in $ac_header_c_list
do
diff --git a/configure.ac b/configure.ac
index 220423cd9a94..f53955ecea19 100644
--- a/configure.ac
+++ b/configure.ac
@@ -113,9 +113,7 @@ AC_PROG_CXX
AM_PROG_AR
AX_CXX_COMPILE_STDCXX(20, noext, mandatory)
KYUA_DEVELOPER_MODE([C++])
-KYUA_ATTRIBUTE_NORETURN
KYUA_ATTRIBUTE_PURE
-KYUA_ATTRIBUTE_UNUSED
KYUA_FS_MODULE
KYUA_GETOPT
KYUA_LAST_SIGNO
diff --git a/doc/kyuafile.5.in b/doc/kyuafile.5.in
index 04480ecfe759..ae4b8ebfa3fe 100644
--- a/doc/kyuafile.5.in
+++ b/doc/kyuafile.5.in
@@ -499,7 +499,7 @@ plain_test_program{name='the_test',
.Ss FreeBSD jail execution environment
The following example configures the test to be run within a temporary jail
with
-.Xr vnet 9
+.Xr VNET 9
support and the permission to create raw sockets:
.Bd -literal -offset indent
syntax(2)
diff --git a/engine/atf.hpp b/engine/atf.hpp
index 34ddc2413235..b9821e5fb7a7 100644
--- a/engine/atf.hpp
+++ b/engine/atf.hpp
@@ -40,23 +40,24 @@ namespace engine {
/// Implementation of the scheduler interface for atf test programs.
class atf_interface : public engine::scheduler::interface {
public:
- void exec_list(const model::test_program&,
- const utils::config::properties_map&) const UTILS_NORETURN;
+ void exec_list [[noreturn]] (
+ const model::test_program&,
+ const utils::config::properties_map&) const;
model::test_cases_map parse_list(
const utils::optional< utils::process::status >&,
const utils::fs::path&,
const utils::fs::path&) const;
- void exec_test(const model::test_program&, const std::string&,
- const utils::config::properties_map&,
- const utils::fs::path&) const
- UTILS_NORETURN;
+ void exec_test [[noreturn]] (
+ const model::test_program&, const std::string&,
+ const utils::config::properties_map&,
+ const utils::fs::path&) const;
- void exec_cleanup(const model::test_program&, const std::string&,
- const utils::config::properties_map&,
- const utils::fs::path&) const
- UTILS_NORETURN;
+ void exec_cleanup [[noreturn]](
+ const model::test_program&, const std::string&,
+ const utils::config::properties_map&,
+ const utils::fs::path&) const;
model::test_result compute_result(
const utils::optional< utils::process::status >&,
diff --git a/engine/debugger.hpp b/engine/debugger.hpp
index 3c4d087f8ad0..ce87d41ed94d 100644
--- a/engine/debugger.hpp
+++ b/engine/debugger.hpp
@@ -58,6 +58,13 @@ public:
const model::test_case&,
optional< model::test_result >&,
executor::exit_handle&) const = 0;
+
+ /// Called upon test failure.
+ virtual void upon_test_failure(
+ const model::test_program_ptr&,
+ const model::test_case&,
+ optional< model::test_result >&,
+ executor::exit_handle&) const = 0;
};
diff --git a/engine/execenv/execenv.hpp b/engine/execenv/execenv.hpp
index a0e5bf043e53..d167196c7e98 100644
--- a/engine/execenv/execenv.hpp
+++ b/engine/execenv/execenv.hpp
@@ -83,7 +83,7 @@ public:
/// scheduler::interface::exec_test() or exec_cleanup().
///
/// \param args The arguments to pass to the binary.
- virtual void exec(const args_vector& args) const UTILS_NORETURN = 0;
+ virtual void exec [[noreturn]] (const args_vector& args) const = 0;
};
diff --git a/engine/execenv/execenv_host.hpp b/engine/execenv/execenv_host.hpp
index 2742366cfd6f..3276ad210574 100644
--- a/engine/execenv/execenv_host.hpp
+++ b/engine/execenv/execenv_host.hpp
@@ -53,7 +53,7 @@ public:
void init() const;
void cleanup() const;
- void exec(const args_vector& args) const UTILS_NORETURN;
+ void exec [[noreturn]] (const args_vector& args) const;
};
diff --git a/engine/googletest.cpp b/engine/googletest.cpp
index d03a7bd82de7..e050410ba1f5 100644
--- a/engine/googletest.cpp
+++ b/engine/googletest.cpp
@@ -191,6 +191,7 @@ engine::googletest_interface::exec_test(
F("--gtest_filter=%s") % (test_case_name)
};
process::exec(test_program.absolute_path(), args);
+ __builtin_unreachable();
}
diff --git a/engine/googletest.hpp b/engine/googletest.hpp
index fb9a7e97adf2..9628f994a066 100644
--- a/engine/googletest.hpp
+++ b/engine/googletest.hpp
@@ -40,18 +40,19 @@ namespace engine {
/// Implementation of the scheduler interface for googletest test programs.
class googletest_interface : public engine::scheduler::interface {
public:
- void exec_list(const model::test_program&,
- const utils::config::properties_map&) const UTILS_NORETURN;
+ void exec_list [[noreturn]] (
+ const model::test_program&,
+ const utils::config::properties_map&) const;
model::test_cases_map parse_list(
const utils::optional< utils::process::status >&,
const utils::fs::path&,
const utils::fs::path&) const;
- void exec_test(const model::test_program&, const std::string&,
- const utils::config::properties_map&,
- const utils::fs::path&) const
- UTILS_NORETURN;
+ void exec_test [[noreturn]] (
+ const model::test_program&, const std::string&,
+ const utils::config::properties_map&,
+ const utils::fs::path&) const;
model::test_result compute_result(
const utils::optional< utils::process::status >&,
diff --git a/engine/plain.hpp b/engine/plain.hpp
index ee5f3e746781..60bffec9bf04 100644
--- a/engine/plain.hpp
+++ b/engine/plain.hpp
@@ -40,18 +40,19 @@ namespace engine {
/// Implementation of the scheduler interface for plain test programs.
class plain_interface : public engine::scheduler::interface {
public:
- void exec_list(const model::test_program&,
- const utils::config::properties_map&) const UTILS_NORETURN;
+ void exec_list [[noreturn]] (
+ const model::test_program&,
+ const utils::config::properties_map&) const;
model::test_cases_map parse_list(
const utils::optional< utils::process::status >&,
const utils::fs::path&,
const utils::fs::path&) const;
- void exec_test(const model::test_program&, const std::string&,
- const utils::config::properties_map&,
- const utils::fs::path&) const
- UTILS_NORETURN;
+ void exec_test [[noreturn]] (
+ const model::test_program&, const std::string&,
+ const utils::config::properties_map&,
+ const utils::fs::path&) const;
model::test_result compute_result(
const utils::optional< utils::process::status >&,
diff --git a/engine/scheduler.cpp b/engine/scheduler.cpp
index 2077ca16df6c..6e19a1598f8c 100644
--- a/engine/scheduler.cpp
+++ b/engine/scheduler.cpp
@@ -87,11 +87,11 @@ using utils::optional;
///
/// TODO(jmmv): This is here only for testing purposes. Maybe we should expose
/// this setting as part of the user_config.
-datetime::delta scheduler::cleanup_timeout(60, 0);
+datetime::delta scheduler::cleanup_timeout(300, 0);
/// Timeout for the test case execenv cleanup operation.
-datetime::delta scheduler::execenv_cleanup_timeout(60, 0);
+datetime::delta scheduler::execenv_cleanup_timeout(300, 0);
/// Timeout for the test case listing operation.
@@ -1403,6 +1403,9 @@ scheduler::scheduler_handle::wait_any(void)
if (debugger) {
debugger->before_cleanup(test_data->test_program, test_case,
result, handle);
+ if (!result.get().good())
+ debugger->upon_test_failure(test_data->test_program, test_case,
+ result, handle);
}
if (test_data->needs_cleanup) {
diff --git a/engine/scheduler.hpp b/engine/scheduler.hpp
index 508a0c0cbfd9..0e241172f1e7 100644
--- a/engine/scheduler.hpp
+++ b/engine/scheduler.hpp
@@ -98,9 +98,9 @@ public:
///
/// \param test_program The test program to execute.
/// \param vars User-provided variables to pass to the test program.
- virtual void exec_list(const model::test_program& test_program,
- const utils::config::properties_map& vars)
- const UTILS_NORETURN = 0;
+ virtual void exec_list [[noreturn]] (
+ const model::test_program& test_program,
+ const utils::config::properties_map& vars) const = 0;
/// Computes the test cases list of a test program.
///
@@ -126,11 +126,11 @@ public:
/// \param vars User-provided variables to pass to the test program.
/// \param control_directory Directory where the interface may place control
/// files.
- virtual void exec_test(const model::test_program& test_program,
- const std::string& test_case_name,
- const utils::config::properties_map& vars,
- const utils::fs::path& control_directory)
- const UTILS_NORETURN = 0;
+ virtual void exec_test [[noreturn]] (
+ const model::test_program& test_program,
+ const std::string& test_case_name,
+ const utils::config::properties_map& vars,
+ const utils::fs::path& control_directory) const = 0;
/// Executes a test cleanup routine of the test program.
///
@@ -143,11 +143,11 @@ public:
/// \param vars User-provided variables to pass to the test program.
/// \param control_directory Directory where the interface may place control
/// files.
- virtual void exec_cleanup(const model::test_program& test_program,
- const std::string& test_case_name,
- const utils::config::properties_map& vars,
- const utils::fs::path& control_directory)
- const UTILS_NORETURN;
+ virtual void exec_cleanup [[noreturn]](
+ const model::test_program& test_program,
+ const std::string& test_case_name,
+ const utils::config::properties_map& vars,
+ const utils::fs::path& control_directory) const;
/// Computes the result of a test case based on its termination status.
///
diff --git a/engine/scheduler_test.cpp b/engine/scheduler_test.cpp
index d91c448f2e5e..93e7627f291a 100644
--- a/engine/scheduler_test.cpp
+++ b/engine/scheduler_test.cpp
@@ -131,7 +131,7 @@ class mock_interface : public scheduler::interface {
///
/// \param exit_code Exit code.
void
- do_exit(const int exit_code) const UTILS_NORETURN
+ do_exit [[noreturn]] (const int exit_code) const
{
std::cout.flush();
std::cerr.flush();
@@ -140,7 +140,7 @@ class mock_interface : public scheduler::interface {
/// Executes a test case that creates various files and then fails.
void
- exec_create_files_and_fail(void) const UTILS_NORETURN
+ exec_create_files_and_fail [[noreturn]] (void) const
{
std::cerr << "This should not be clobbered\n";
atf::utils::create_file("first file", "");
@@ -155,7 +155,7 @@ class mock_interface : public scheduler::interface {
/// This is intended to validate that the test runs in an empty directory,
/// separate from any control files that the scheduler may have created.
void
- exec_delete_all(void) const UTILS_NORETURN
+ exec_delete_all [[noreturn]] (void) const
{
const int exit_code = ::system("rm *") == -1
? EXIT_FAILURE : EXIT_SUCCESS;
@@ -170,14 +170,14 @@ class mock_interface : public scheduler::interface {
///
/// \param exit_code Exit status to terminate the program with.
void
- exec_exit(const int exit_code) const UTILS_NORETURN
+ exec_exit [[noreturn]] (const int exit_code) const
{
do_exit(exit_code);
}
/// Executes a test case that just fails.
void
- exec_fail(void) const UTILS_NORETURN
+ exec_fail [[noreturn]] (void) const
{
std::cerr << "This should not be clobbered\n";
::kill(::getpid(), SIGTERM);
@@ -191,10 +191,10 @@ class mock_interface : public scheduler::interface {
/// number.
/// \param vars User-provided variables to pass to the test program.
void
- exec_print_params(const model::test_program& test_program,
- const std::string& test_case_name,
- const config::properties_map& vars) const
- UTILS_NORETURN
+ exec_print_params [[noreturn]] (
+ const model::test_program& test_program,
+ const std::string& test_case_name,
+ const config::properties_map& vars) const
{
std::cout << F("Test program: %s\n") % test_program.relative_path();
std::cout << F("Test case: %s\n") % test_case_name;
@@ -218,9 +218,9 @@ public:
/// \param test_program The test program to execute.
/// \param vars User-provided variables to pass to the test program.
void
- exec_list(const model::test_program& test_program,
- const config::properties_map& vars)
- const UTILS_NORETURN
+ exec_list [[noreturn]] (
+ const model::test_program& test_program,
+ const config::properties_map& vars) const
{
const std::string name = test_program.absolute_path().leaf_name();
diff --git a/engine/tap.hpp b/engine/tap.hpp
index b46bf28f0240..51ad76231eaf 100644
--- a/engine/tap.hpp
+++ b/engine/tap.hpp
@@ -40,18 +40,19 @@ namespace engine {
/// Implementation of the scheduler interface for tap test programs.
class tap_interface : public engine::scheduler::interface {
public:
- void exec_list(const model::test_program&,
- const utils::config::properties_map&) const UTILS_NORETURN;
+ void exec_list [[noreturn]] (
+ const model::test_program&,
+ const utils::config::properties_map&) const;
model::test_cases_map parse_list(
const utils::optional< utils::process::status >&,
const utils::fs::path&,
const utils::fs::path&) const;
- void exec_test(const model::test_program&, const std::string&,
- const utils::config::properties_map&,
- const utils::fs::path&) const
- UTILS_NORETURN;
+ void exec_test [[noreturn]] (
+ const model::test_program&, const std::string&,
+ const utils::config::properties_map&,
+ const utils::fs::path&) const;
model::test_result compute_result(
const utils::optional< utils::process::status >&,
diff --git a/m4/compiler-features.m4 b/m4/compiler-features.m4
index 840f292383d5..5d2bc92229b1 100644
--- a/m4/compiler-features.m4
+++ b/m4/compiler-features.m4
@@ -27,39 +27,6 @@ dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
dnl
-dnl KYUA_ATTRIBUTE_NORETURN
-dnl
-dnl Checks if the current compiler has a way to mark functions that do not
-dnl return and defines ATTRIBUTE_NORETURN to the appropriate string.
-dnl
-AC_DEFUN([KYUA_ATTRIBUTE_NORETURN], [
- dnl This check is overly simple and should be fixed. For example,
- dnl Sun's cc does support the noreturn attribute but CC (the C++
- dnl compiler) does not. And in that case, CC just raises a warning
- dnl during compilation, not an error.
- AC_CACHE_CHECK(
- [whether __attribute__((noreturn)) is supported],
- [kyua_cv_attribute_noreturn], [
- AC_RUN_IFELSE([AC_LANG_PROGRAM([], [
-#if ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
- return 0;
-#else
- return 1;
-#endif
- ])],
- [kyua_cv_attribute_noreturn=yes],
- [kyua_cv_attribute_noreturn=no])
- ])
- if test "${kyua_cv_attribute_noreturn}" = yes; then
- attribute_value="__attribute__((noreturn))"
- else
- attribute_value=""
- fi
- AC_SUBST([ATTRIBUTE_NORETURN], [${attribute_value}])
-])
-
-
-dnl
dnl KYUA_ATTRIBUTE_PURE
dnl
dnl Checks if the current compiler has a way to mark functions as pure.
@@ -89,34 +56,3 @@ function(int a, int b)
fi
AC_SUBST([ATTRIBUTE_PURE], [${attribute_value}])
])
-
-
-dnl
-dnl KYUA_ATTRIBUTE_UNUSED
-dnl
-dnl Checks if the current compiler has a way to mark parameters as unused
-dnl so that the -Wunused-parameter warning can be avoided.
-dnl
-AC_DEFUN([KYUA_ATTRIBUTE_UNUSED], [
- AC_CACHE_CHECK(
- [whether __attribute__((__unused__)) is supported],
- [kyua_cv_attribute_unused], [
- AC_COMPILE_IFELSE(
- [AC_LANG_PROGRAM([
-static void
-function(int a __attribute__((__unused__)))
-{
-}], [
- function(3);
- return 0;
-])],
- [kyua_cv_attribute_unused=yes],
- [kyua_cv_attribute_unused=no])
- ])
- if test "${kyua_cv_attribute_unused}" = yes; then
- attribute_value="__attribute__((__unused__))"
- else
- attribute_value=""
- fi
- AC_SUBST([ATTRIBUTE_UNUSED], [${attribute_value}])
-])
diff --git a/os/freebsd/execenv_jail.hpp b/os/freebsd/execenv_jail.hpp
index e6d2c2e42497..73365316dae1 100644
--- a/os/freebsd/execenv_jail.hpp
+++ b/os/freebsd/execenv_jail.hpp
@@ -56,7 +56,7 @@ public:
void init() const;
void cleanup() const;
- void exec(const args_vector& args) const UTILS_NORETURN;
+ void exec [[noreturn]] (const args_vector& args) const;
};
diff --git a/os/freebsd/execenv_jail_stub.cpp b/os/freebsd/execenv_jail_stub.cpp
index 9425618e2b5a..4634f4ef80c9 100644
--- a/os/freebsd/execenv_jail_stub.cpp
+++ b/os/freebsd/execenv_jail_stub.cpp
@@ -35,7 +35,7 @@
using utils::process::args_vector;
-static inline void requires_freebsd(void) UTILS_NORETURN;
+static inline void requires_freebsd [[noreturn]] (void);
static inline void
requires_freebsd(void)
diff --git a/os/freebsd/reqs_checker_kmods.cpp b/os/freebsd/reqs_checker_kmods.cpp
index 3ae3446a7815..ce17caeaeb8d 100644
--- a/os/freebsd/reqs_checker_kmods.cpp
+++ b/os/freebsd/reqs_checker_kmods.cpp
@@ -31,7 +31,7 @@
#include "model/metadata.hpp"
extern "C" {
-#include "libutil.h"
+#include <libutil.h>
}
std::string
diff --git a/os/freebsd/utils/jail.hpp b/os/freebsd/utils/jail.hpp
index 5b972155cd25..44730493a7d0 100644
--- a/os/freebsd/utils/jail.hpp
+++ b/os/freebsd/utils/jail.hpp
@@ -51,9 +51,10 @@ public:
const std::string& test_case_name);
void create(const std::string& jail_name,
const std::string& jail_params);
- void exec(const std::string& jail_name,
- const fs::path& program,
- const args_vector& args) throw() UTILS_NORETURN;
+ void exec [[noreturn]] (
+ const std::string& jail_name,
+ const fs::path& program,
+ const args_vector& args) throw();
void remove(const std::string& jail_name);
};
diff --git a/utils/cmdline/options.cpp b/utils/cmdline/options.cpp
index 61736e31c11e..9d448503e3f9 100644
--- a/utils/cmdline/options.cpp
+++ b/utils/cmdline/options.cpp
@@ -53,15 +53,18 @@ namespace text = utils::text;
/// purposes.
/// \param default_value_ If not NULL, specifies that the option has a default
/// value for the mandatory argument.
+/// \param arg_is_optional_ Specifies if a value must be provided or not.
cmdline::base_option::base_option(const char short_name_,
const char* long_name_,
const char* description_,
const char* arg_name_,
- const char* default_value_) :
+ const char* default_value_,
+ bool arg_is_optional_) :
_short_name(short_name_),
_long_name(long_name_),
_description(description_),
_arg_name(arg_name_ == NULL ? "" : arg_name_),
+ _arg_is_optional(arg_is_optional_),
_has_default_value(default_value_ != NULL),
_default_value(default_value_ == NULL ? "" : default_value_)
{
@@ -164,6 +167,16 @@ cmdline::base_option::arg_name(void) const
}
+/// Returns optionality of the argument.
+///
+/// \return The optionality.
+bool
+cmdline::base_option::arg_is_optional(void) const
+{
+ return _arg_is_optional;
+}
+
+
/// Checks whether the option has a default value for its argument.
///
/// \pre needs_arg() must be true.
@@ -558,9 +571,10 @@ cmdline::string_option::string_option(const char short_name_,
const char* long_name_,
const char* description_,
const char* arg_name_,
- const char* default_value_) :
+ const char* default_value_,
+ bool arg_is_optional_) :
base_option(short_name_, long_name_, description_, arg_name_,
- default_value_)
+ default_value_, arg_is_optional_)
{
}
diff --git a/utils/cmdline/options.hpp b/utils/cmdline/options.hpp
index f3a83889e491..d11de14af514 100644
--- a/utils/cmdline/options.hpp
+++ b/utils/cmdline/options.hpp
@@ -91,6 +91,9 @@ class base_option {
/// Descriptive name of the required argument; empty if not allowed.
std::string _arg_name;
+ /// If the option can be used without an explicit argument provided.
+ bool _arg_is_optional = false;
+
/// Whether the option has a default value or not.
///
/// \todo We should probably be using the optional class here.
@@ -101,7 +104,7 @@ class base_option {
public:
base_option(const char, const char*, const char*, const char* = NULL,
- const char* = NULL);
+ const char* = NULL, bool = false);
base_option(const char*, const char*, const char* = NULL,
const char* = NULL);
virtual ~base_option(void);
@@ -113,6 +116,7 @@ public:
bool needs_arg(void) const;
const std::string& arg_name(void) const;
+ bool arg_is_optional(void) const;
bool has_default_value(void) const;
const std::string& default_value(void) const;
@@ -219,7 +223,7 @@ public:
class string_option : public base_option {
public:
string_option(const char, const char*, const char*, const char*,
- const char* = NULL);
+ const char* = NULL, bool = false);
string_option(const char*, const char*, const char*, const char* = NULL);
virtual ~string_option(void) {}
diff --git a/utils/cmdline/parser.cpp b/utils/cmdline/parser.cpp
index 5c83f6d69cc4..29dd4612f6ad 100644
--- a/utils/cmdline/parser.cpp
+++ b/utils/cmdline/parser.cpp
@@ -88,7 +88,10 @@ options_to_getopt_data(const cmdline::options_vector& options,
long_option.name = option->long_name().c_str();
if (option->needs_arg())
- long_option.has_arg = required_argument;
+ if (option->arg_is_optional())
+ long_option.has_arg = optional_argument;
+ else
+ long_option.has_arg = required_argument;
else
long_option.has_arg = no_argument;
@@ -96,7 +99,7 @@ options_to_getopt_data(const cmdline::options_vector& options,
if (option->has_short_name()) {
data.short_options += option->short_name();
if (option->needs_arg())
- data.short_options += ':';
+ data.short_options += option->arg_is_optional() ? "::" : ":";
id = option->short_name();
} else {
id = cur_id++;
@@ -320,9 +323,11 @@ cmdline::parse(const int argc, const char* const* argv,
for (cmdline::options_vector::const_iterator iter = options.begin();
iter != options.end(); iter++) {
const cmdline::base_option* option = *iter;
- if (option->needs_arg() && option->has_default_value())
+ if (option->needs_arg() && option->has_default_value() &&
+ !option->arg_is_optional()) {
option_values[option->long_name()].push_back(
option->default_value());
+ }
}
args_vector args;
@@ -357,8 +362,13 @@ cmdline::parse(const int argc, const char* const* argv,
if (::optarg != NULL) {
option->validate(::optarg);
option_values[option->long_name()].push_back(::optarg);
- } else
- INV(option->has_default_value());
+ } else {
+ if (option->arg_is_optional())
+ option_values[option->long_name()].push_back(
+ option->default_value());
+ else
+ INV(option->has_default_value());
+ }
} else {
option_values[option->long_name()].push_back("");
}
diff --git a/utils/defs.hpp.in b/utils/defs.hpp.in
index 7290980a6f6f..88207c90aa58 100644
--- a/utils/defs.hpp.in
+++ b/utils/defs.hpp.in
@@ -38,23 +38,13 @@ extern "C" {
#include <inttypes.h>
}
-/// Attribute to mark a function as non-returning.
-#define UTILS_NORETURN @ATTRIBUTE_NORETURN@
-
-
/// Attribute to mark a function as pure.
#define UTILS_PURE @ATTRIBUTE_PURE@
-
-/// Attribute to mark an entity as unused.
-#define UTILS_UNUSED @ATTRIBUTE_UNUSED@
-
-
/// Unconstifies a pointer.
///
/// \param type The target type of the conversion.
/// \param ptr The pointer to be unconstified.
#define UTILS_UNCONST(type, ptr) ((type*)(uintptr_t)(const void*)(ptr))
-
#endif // !defined(UTILS_DEFS_HPP)
diff --git a/utils/fs/operations.cpp b/utils/fs/operations.cpp
index 185d164b88d7..4e1bb294a228 100644
--- a/utils/fs/operations.cpp
+++ b/utils/fs/operations.cpp
@@ -148,7 +148,7 @@ unmount(const char* /* path */,
const int exit_known_error = 123;
-static void run_mount_tmpfs(const fs::path&, const uint64_t) UTILS_NORETURN;
+static void run_mount_tmpfs [[noreturn]] (const fs::path&, const uint64_t);
/// Executes 'mount -t tmpfs' (or a similar variant).
diff --git a/utils/process/child.cpp b/utils/process/child.cpp
index 36b6b6b3e51f..c51c39e6d1ff 100644
--- a/utils/process/child.cpp
+++ b/utils/process/child.cpp
@@ -235,6 +235,30 @@ process::child::fork_capture_aux(void)
}
+std::unique_ptr< process::child >
+process::child::fork_interactive(void)
+{
+ std::cout.flush();
+ std::cerr.flush();
+
+ std::unique_ptr< signals::interrupts_inhibiter > inhibiter(
+ new signals::interrupts_inhibiter);
+ pid_t pid = detail::syscall_fork();
+ if (pid == -1) {
+ inhibiter.reset(); // Unblock signals.
+ throw process::system_error("fork(2) failed", errno);
+ } else if (pid == 0) {
+ inhibiter.reset(); // Unblock signals.
+ return {};
+ } else {
+ signals::add_pid_to_kill(pid);
+ inhibiter.reset(NULL); // Unblock signals.
+ return std::unique_ptr< process::child >(
+ new process::child(new impl(pid, NULL)));
+ }
+}
+
+
/// Helper function for fork().
///
/// Please note: if you update this function to change the return type or to
diff --git a/utils/process/child.hpp b/utils/process/child.hpp
index 3e00cea8752c..bddf4b67fe0b 100644
--- a/utils/process/child.hpp
+++ b/utils/process/child.hpp
@@ -64,8 +64,8 @@ namespace process {
namespace detail {
-void report_error_and_abort(void) UTILS_NORETURN;
-void report_error_and_abort(const std::runtime_error&) UTILS_NORETURN;
+void report_error_and_abort [[noreturn]] (void);
+void report_error_and_abort [[noreturn]] (const std::runtime_error&);
} // namespace detail
@@ -80,6 +80,8 @@ class child : noncopyable {
static std::unique_ptr< child > fork_capture_aux(void);
+ static std::unique_ptr< child > fork_interactive(void);
+
static std::unique_ptr< child > fork_files_aux(const fs::path&,
const fs::path&);
@@ -93,6 +95,9 @@ public:
std::istream& output(void);
template< typename Hook >
+ static std::unique_ptr< child > fork_interactive(Hook);
+
+ template< typename Hook >
static std::unique_ptr< child > fork_files(Hook, const fs::path&,
const fs::path&);
diff --git a/utils/process/child.ipp b/utils/process/child.ipp
index beb2ea3b0b0a..86bc01fc0d6e 100644
--- a/utils/process/child.ipp
+++ b/utils/process/child.ipp
@@ -104,6 +104,26 @@ child::fork_capture(Hook hook)
}
+template< typename Hook >
+std::unique_ptr< child >
+child::fork_interactive(Hook hook)
+{
+ std::unique_ptr< child > child = fork_interactive();
+ if (child.get() == NULL) {
+ try {
+ hook();
+ std::abort();
+ } catch (const std::runtime_error& e) {
+ detail::report_error_and_abort(e);
+ } catch (...) {
+ detail::report_error_and_abort();
+ }
+ }
+
+ return child;
+}
+
+
} // namespace process
} // namespace utils
diff --git a/utils/process/executor_test.cpp b/utils/process/executor_test.cpp
index 13ae69bd44ed..b52730b5c71c 100644
--- a/utils/process/executor_test.cpp
+++ b/utils/process/executor_test.cpp
@@ -80,7 +80,7 @@ using utils::optional;
static const datetime::delta infinite_timeout(1000000, 0);
-static void do_exit(const int) UTILS_NORETURN;
+static void do_exit [[noreturn]] (const int);
/// Terminates a subprocess without invoking destructors.
@@ -118,8 +118,7 @@ public:
/// Runs the subprocess.
void
- operator()(const fs::path& /* control_directory */)
- UTILS_NORETURN
+ operator() [[noreturn]] (const fs::path& /* control_directory */)
{
std::cout << "Creating cookie: " << _cookie_name << " (stdout)\n";
std::cerr << "Creating cookie: " << _cookie_name << " (stderr)\n";
@@ -129,7 +128,7 @@ public:
};
-static void child_delete_all(const fs::path&) UTILS_NORETURN;
+static void child_delete_all [[noreturn]] (const fs::path&);
/// Subprocess that deletes all files in the current directory.
@@ -155,7 +154,7 @@ child_delete_all(const fs::path& control_directory)
}
-static void child_dump_unprivileged_user(const fs::path&) UTILS_NORETURN;
+static void child_dump_unprivileged_user [[noreturn]] (const fs::path&);
/// Subprocess that dumps user configuration.
@@ -183,15 +182,14 @@ public:
/// Runs the subprocess.
void
- operator()(const fs::path& /* control_directory */)
- UTILS_NORETURN
+ operator() [[noreturn]] (const fs::path& /* control_directory */)
{
do_exit(_exit_code);
}
};
-static void child_pause(const fs::path&) UTILS_NORETURN;
+static void child_pause [[noreturn]] (const fs::path&);
/// Subprocess that just blocks.
@@ -207,7 +205,7 @@ child_pause(const fs::path& /* control_directory */)
}
-static void child_print(const fs::path&) UTILS_NORETURN;
+static void child_print [[noreturn]] (const fs::path&);
/// Subprocess that writes to stdout and stderr.
@@ -236,8 +234,7 @@ public:
/// Runs the subprocess.
void
- operator()(const fs::path& /* control_directory */)
- UTILS_NORETURN
+ operator() [[noreturn]] (const fs::path& /* control_directory */)
{
::sleep(_seconds);
do_exit(EXIT_SUCCESS);
@@ -245,7 +242,7 @@ public:
};
-static void child_spawn_blocking_child(const fs::path&) UTILS_NORETURN;
+static void child_spawn_blocking_child [[noreturn]] (const fs::path&);
/// Subprocess that spawns a subchild that gets stuck.
@@ -278,7 +275,7 @@ child_spawn_blocking_child(
}
-static void child_validate_isolation(const fs::path&) UTILS_NORETURN;
+static void child_validate_isolation [[noreturn]] (const fs::path&);
/// Subprocess that checks if isolate_child() has been called.
diff --git a/utils/process/isolation.cpp b/utils/process/isolation.cpp
index 90dd08d5772d..3b2ecaa3e992 100644
--- a/utils/process/isolation.cpp
+++ b/utils/process/isolation.cpp
@@ -67,7 +67,7 @@ const int process::exit_isolation_failure = 124;
namespace {
-static void fail(const std::string&, const int) UTILS_NORETURN;
+static void fail [[noreturn]] (const std::string&, const int);
/// Fails the process with an errno-based error message.
diff --git a/utils/process/operations.hpp b/utils/process/operations.hpp
index 773f9d38bb74..781d7d84af8e 100644
--- a/utils/process/operations.hpp
+++ b/utils/process/operations.hpp
@@ -42,10 +42,10 @@ namespace utils {
namespace process {
-void exec(const utils::fs::path&, const args_vector&) throw() UTILS_NORETURN;
-void exec_unsafe(const utils::fs::path&, const args_vector&) UTILS_NORETURN;
+void exec [[noreturn]] (const utils::fs::path&, const args_vector&) throw();
+void exec_unsafe [[noreturn]] (const utils::fs::path&, const args_vector&);
void terminate_group(const int);
-void terminate_self_with(const status&) UTILS_NORETURN;
+void terminate_self_with [[noreturn]] (const status&);
status wait(const int);
status wait_any(void);
diff --git a/utils/process/operations_test.cpp b/utils/process/operations_test.cpp
index d30dc890abd2..863e0937fe0a 100644
--- a/utils/process/operations_test.cpp
+++ b/utils/process/operations_test.cpp
@@ -117,7 +117,7 @@ child_exit(void)
}
-static void suspend(void) UTILS_NORETURN;
+static void suspend [[noreturn]] (void);
/// Blocks a subprocess from running indefinitely.
@@ -132,7 +132,7 @@ suspend(void)
}
-static void write_loop(const int) UTILS_NORETURN;
+static void write_loop [[noreturn]] (const int);
/// Provides an infinite stream of data in a subprocess.
diff --git a/utils/sanity.hpp b/utils/sanity.hpp
index 6b126f984999..d4bde12e8060 100644
--- a/utils/sanity.hpp
+++ b/utils/sanity.hpp
@@ -49,8 +49,8 @@
namespace utils {
-void sanity_failure(const assert_type, const char*, const size_t,
- const std::string&) UTILS_NORETURN;
+void sanity_failure [[noreturn]](
+ const assert_type, const char*, const size_t, const std::string&);
void install_crash_handlers(const std::string&);
diff --git a/utils/signals/misc_test.cpp b/utils/signals/misc_test.cpp
index 3b6d57325ee1..398cf50c4c2b 100644
--- a/utils/signals/misc_test.cpp
+++ b/utils/signals/misc_test.cpp
@@ -51,7 +51,7 @@ namespace signals = utils::signals;
namespace {
-static void program_reset_raise(void) UTILS_NORETURN;
+static void program_reset_raise [[noreturn]] (void);
/// Body of a subprocess that tests the signals::reset function.
diff --git a/utils/sqlite/test_utils.hpp b/utils/sqlite/test_utils.hpp
index bf35d209a164..ba6b720b57ed 100644
--- a/utils/sqlite/test_utils.hpp
+++ b/utils/sqlite/test_utils.hpp
@@ -97,7 +97,7 @@ static const char* create_test_table_sql =
"INSERT INTO test (prime) VALUES (3);\n";
-static void create_test_table(::sqlite3*) UTILS_UNUSED;
+[[maybe_unused]] void create_test_table(::sqlite3*);
/// Creates a 'test' table in a database.
@@ -118,7 +118,7 @@ create_test_table(::sqlite3* db)
}
-static void verify_test_table(::sqlite3*) UTILS_UNUSED;
+[[maybe_unused]] void verify_test_table(::sqlite3*);
/// Verifies that the specified database contains the 'test' table.
diff --git a/utils/stacktrace.cpp b/utils/stacktrace.cpp
index 11636b31959f..30d8459c98c3 100644
--- a/utils/stacktrace.cpp
+++ b/utils/stacktrace.cpp
@@ -77,7 +77,7 @@ const char* utils::builtin_gdb = GDB;
/// Maximum time the external GDB process is allowed to run for.
-datetime::delta utils::gdb_timeout(60, 0);
+datetime::delta utils::gdb_timeout(300, 0);
namespace {
diff --git a/utils/stacktrace_test.cpp b/utils/stacktrace_test.cpp
index ca87e7087f5a..e3b170755764 100644
--- a/utils/stacktrace_test.cpp
+++ b/utils/stacktrace_test.cpp
@@ -94,7 +94,7 @@ public:
/// Runs the binary.
void
- operator()(void) const UTILS_NORETURN
+ operator() [[noreturn]] (void) const
{
atf::utils::copy_file(_binary.str(), _copy_name.str());
@@ -106,15 +106,14 @@ public:
///
/// This interface is exposed to support passing crash_me to the executor.
void
- operator()(const fs::path& /* control_directory */) const
- UTILS_NORETURN
+ operator() [[noreturn]] (const fs::path& /* control_directory */) const
{
(*this)(); // Delegate to ensure the two entry points remain in sync.
}
};
-static void child_exit(const fs::path&) UTILS_NORETURN;
+static void child_exit [[noreturn]] (const fs::path&);
/// Subprocess that exits cleanly.
@@ -125,7 +124,7 @@ child_exit(const fs::path& /* control_directory */)
}
-static void child_pause(const fs::path&) UTILS_NORETURN;
+static void child_pause [[noreturn]] (const fs::path&);
/// Subprocess that just blocks.
diff --git a/utils/test_utils.ipp b/utils/test_utils.ipp
index f21d0f4cc172..60b92adf5463 100644
--- a/utils/test_utils.ipp
+++ b/utils/test_utils.ipp
@@ -67,7 +67,7 @@ avoid_coredump_on_crash(void)
}
-inline void abort_without_coredump(void) UTILS_NORETURN;
+inline void abort_without_coredump [[noreturn]] (void);
/// Aborts execution and tries to not dump core.
diff --git a/utils/text/regex.cpp b/utils/text/regex.cpp
index b078ba88f6b4..86b41cc872aa 100644
--- a/utils/text/regex.cpp
+++ b/utils/text/regex.cpp
@@ -47,8 +47,8 @@ namespace text = utils::text;
namespace {
-static void throw_regex_error(const int, const ::regex_t*, const std::string&)
- UTILS_NORETURN;
+static void throw_regex_error [[noreturn]] (
+ const int, const ::regex_t*, const std::string&);
/// Constructs and raises a regex_error.