#define CATCH_CONFIG_RUNNER
#include "lib/catch.hpp"
-#include "mem_config.h"
-#include <cstdlib>
-
-#if HAVE_SETENV
-# define SET_ENV(n, k, v) setenv(k, v, 0);
-#else // !HAVE_SETENV
-# define SET_ENV(n, k, v) static char n ## _env[] = k "=" v; putenv(n ## _env)
-#endif
+#include "setup.hpp"
int main(int argc, char *argv[]) {
-
-#if HAVE_ASAN
- SET_ENV(asan, "ASAN_OPTIONS", "halt_on_error=0")
-#endif
-
-#if LIBMEMCACHED_WITH_SASL_SUPPORT
- SET_ENV(sasl_pwdb, "MEMCACHED_SASL_PWDB", LIBMEMCACHED_WITH_SASL_PWDB);
- SET_ENV(sasl_conf, "SASL_CONF_PATH", LIBMEMCACHED_WITH_SASL_CONF);
-#endif
-
+ setup(argc, &argv);
return Catch::Session().run(argc, argv);
}
--- /dev/null
+#include "mem_config.h"
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#include <csignal>
+#include <iostream>
+#include <string>
+#include <unistd.h>
+
+#if HAVE_SETENV
+# define SET_ENV(n, k, v) setenv(k, v, 0)
+#else // !HAVE_SETENV
+# define SET_ENV(n, k, v) static char n ## _env[] = k "=" v; putenv(n ## _env)
+#endif
+
+static void sigchld(int, siginfo_t *si, void *) {
+ switch (si->si_code) {
+ case CLD_EXITED:
+ // expected
+ break;
+ case CLD_KILLED:
+ if (si->si_status == SIGKILL) {
+ // expected
+ break;
+ }
+ [[fallthrough]];
+ case CLD_DUMPED:
+ std::cerr << "Server{pid="
+ << std::to_string(si->si_pid)
+ << "} died: "
+ << strsignal(si->si_status)
+ << std::endl;
+ break;
+ }
+}
+
+static inline void setup_signals() {
+ struct sigaction sa;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_flags = SA_NOCLDSTOP | SA_RESTART | SA_SIGINFO | SA_NODEFER;
+
+ sa.sa_sigaction = sigchld;
+ if (0 > sigaction(SIGCHLD, &sa, nullptr)) {
+ perror("sigaction(CHLD)");
+ }
+}
+
+#if HAVE_ASAN
+// this has to be a macro for putenv() to work
+# define ASAN_OPTIONS \
+ "check_initialization_order=1," \
+ "replace_str=1," \
+ "replace_intrin=1," \
+ "detect_stack_use_after_return=1," \
+ "alloc_dealloc_mismatch=1," \
+ "new_delete_type_mismatch=1," \
+ "detect_odr_violation=2," \
+ "halt_on_error=0," \
+ "verify_asan_link_order=1," \
+ "abort_on_error=0," \
+ ""
+static inline void setup_asan(char **argv) {
+ const auto set = getenv("ASAN_OPTIONS");
+
+ if (!set || !*set) {
+ SET_ENV(asan, "ASAN_OPTIONS", ASAN_OPTIONS);
+ execvp(argv[0], argv);
+ perror("exec()");
+ }
+}
+#else
+# define setup_asan(a)
+#endif
+
+#if LIBMEMCACHED_WITH_SASL_SUPPORT
+static inline void setup_sasl() {
+ SET_ENV(sasl_pwdb, "MEMCACHED_SASL_PWDB", LIBMEMCACHED_WITH_SASL_PWDB);
+ SET_ENV(sasl_conf, "SASL_CONF_PATH", LIBMEMCACHED_WITH_SASL_CONF);
+}
+#else
+# define setup_sasl()
+#endif
+
+int setup(int &, char ***argv) {
+ setup_signals();
+ setup_asan(*argv);
+ setup_sasl();
+
+ return 0;
+}