cpu_handler handler_avg ("avg"), handler_peak ("peak");
+static void try_kill (pid_t child)
+{
+ if (kill (child, SIGKILL) == -1)
+ throw_errno ("kill(" + std::to_string(child) + ", SIGKILL) failed");
+}
+
int main (int argc, char ** argv)
{
const std::vector <std::pair <bool (*) (), std::string>> test_cases
handler_avg .child_pid = child;
if (! run_throttled (child, 60, & handler_peak, TEST_TIME_PEAK)) {
- kill (child, SIGKILL);
+ try_kill (child);
return false;
}
std::this_thread::sleep_for (CATCH_STRAGGLER_SIGNALS_TIME);
bool ret = ! run_throttled (child, 60, & handler_avg , TEST_TIME_AVG - TEST_TIME_PEAK);
- kill (child, SIGKILL);
+ try_kill (child);
return ret;
}
} , "running at ~60% CPU (using SIGSTOP/SIGCONT on child), expecting average signal (but not peak)"
for (const auto fd : fds)
if (fd != -1)
- close (fd);
+ if (close (fd) == -1)
+ throw_errno ("close() failed");
return nullptr;
}
* the sum of both matters and it's good not to have to keep
* extra files on the disk to read from. */
- static constexpr const char * IN_FILE_PATH = "/dev/zero";
- static constexpr const char * OUT_FILE_PATH = "/opt/usr/stability-test.out";
+ static const std::string IN_FILE_PATH = "/dev/zero";
+ static const std::string OUT_FILE_PATH = "/opt/usr/stability-test.out";
std::ifstream in ( IN_FILE_PATH, std::ifstream::binary);
std::ofstream out (OUT_FILE_PATH, std::ofstream::binary);
if (! in.good ()
|| ! out.good ())
- throw std::runtime_error (std::string("Couldn't open ") + IN_FILE_PATH + " and " + OUT_FILE_PATH);
+ throw std::runtime_error ("Couldn't open " + IN_FILE_PATH + " and " + OUT_FILE_PATH);
/* Buffering is undesirable here; it affects the underlying I/O
* in an unpredictable way, ruining measurements. */
in.close ();
out.close ();
- std::remove (OUT_FILE_PATH);
+ if (remove (OUT_FILE_PATH.c_str()) == -1)
+ throw_errno ("remove(" + OUT_FILE_PATH + ") failed");
return nullptr;
}
static void * io_heavy (void * arg)
-{ do_io (10); }
+{ return do_io (10); }
static void * io_light (void * arg)
-{ do_io (1000); }
+{ return do_io (1000); }
static void * io_medium (void * arg)
-{ do_io (40); }
+{ return do_io (40); }
struct io_handler : public dbus_signal_handler {
const std::string limitType;
int main (int argc, char ** argv)
{
- get_total_ram ();
+ try {
+ get_total_ram ();
+ } catch (const std::exception & ex) {
+ std::cout << ex.what () << std::endl;
+ return EXIT_FAILURE;
+ }
const std::vector <std::pair <bool (*) (), std::string>> test_cases
{ { []() {
// C++
#include <chrono>
#include <exception>
-#include <iostream>
#include <fstream>
+#include <iostream>
#include <map>
#include <memory>
#include <numeric>
-#include <system_error>
#include <thread>
#include <vector>
#include <pthread.h>
#include <unistd.h>
-static inline void throw_errno (const std::string & what)
-{ throw std::system_error (errno, std::generic_category (), what); }
-
/* Globals because passing them around would be a massive hassle. */
bool timed_out = false;
bool global_stop = false;
pthread_setaffinity_np (pt, sizeof cpu_set, & cpu_set);
}
+typedef std::pair <thread_func_t *, void *> thread_fwd_t;
+static void * safe_thread (void * params_ptr) try
+{
+ /* Threads can throw exceptions; this wrapper
+ * makes sure that nothing slips through, which
+ * would otherwise crash the entire program. */
+
+ std::unique_ptr <thread_fwd_t> params (reinterpret_cast <thread_fwd_t *> (params_ptr));
+ return params->first (params->second);
+}
+catch (const std::exception & ex)
+{
+ std::cout << "Thread caught exception: " << ex.what () << std::endl;
+ return nullptr;
+}
+catch (...)
+{
+ std::cout << "Thread caught unknown exception" << std::endl;
+ return nullptr;
+}
+
static inline pthread_t spawn_thread (thread_func_t * func, int param)
{
pthread_t pt;
- if (pthread_create(& pt, nullptr, func, reinterpret_cast <void *> (param)))
+ if (pthread_create(& pt, nullptr, safe_thread, new thread_fwd_t (func, reinterpret_cast <void *> (param))))
throw_errno ("pthread_create");
return pt;
}
/* Finish with a SIGSTOP so that heavy throttlees do not
* keep running at full speed and trigger something. */
- kill (throttlee, SIGSTOP);
+ if (kill (throttlee, SIGSTOP) == -1)
+ throw_errno ("kill(" + std::to_string (throttlee) + ", SIGSTOP) failed");
return nullptr;
}
// C++
#include <chrono>
#include <string>
+#include <system_error>
#include <vector>
// POSIX
virtual bool match (const gchar * objpath, const gchar * iface, GVariant * parameters) const = 0;
};
+static inline void throw_errno (const std::string & what)
+{ throw std::system_error (errno, std::generic_category (), what); }
+
extern bool timed_out;
extern bool global_stop;
extern GMainLoop * loop;