2019-10-13 21:06:50 +08:00
|
|
|
#include <sgnl/AtomicCondition.h>
|
|
|
|
#include <sgnl/SignalHandler.h>
|
|
|
|
|
|
|
|
#include <cstdlib>
|
2020-08-01 20:18:12 +08:00
|
|
|
#include <future>
|
2019-10-13 21:06:50 +08:00
|
|
|
#include <iostream>
|
2020-08-01 08:05:43 +08:00
|
|
|
#include <unistd.h>
|
2020-08-01 20:18:12 +08:00
|
|
|
#include <vector>
|
2019-10-13 21:06:50 +08:00
|
|
|
|
|
|
|
|
2020-08-01 20:19:03 +08:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
2019-10-13 21:06:50 +08:00
|
|
|
void Worker(const sgnl::AtomicCondition<bool>& exit_condition)
|
|
|
|
{
|
2020-07-18 06:20:54 +08:00
|
|
|
while( !exit_condition.get() )
|
2019-10-13 21:06:50 +08:00
|
|
|
{
|
|
|
|
/* ... do work ... */
|
2020-07-18 06:20:54 +08:00
|
|
|
|
|
|
|
exit_condition.wait_for_value(true, std::chrono::minutes(1));
|
2019-10-13 21:06:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-01 20:19:03 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-10-13 21:06:50 +08:00
|
|
|
int main()
|
|
|
|
{
|
|
|
|
sgnl::AtomicCondition<bool> exit_condition(false);
|
|
|
|
|
2020-07-18 06:20:54 +08:00
|
|
|
auto my_handler = [&exit_condition](int signum) {
|
2019-10-13 21:06:50 +08:00
|
|
|
std::cout << "received signal " << signum << "\n";
|
|
|
|
if( signum == SIGTERM || signum == SIGINT )
|
|
|
|
{
|
2020-07-18 06:20:54 +08:00
|
|
|
// set atomic<bool> and wakeup all waiting threads
|
|
|
|
exit_condition.set_and_notify_all(true);
|
|
|
|
|
2019-10-13 21:06:50 +08:00
|
|
|
// stop polling for signals
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// continue waiting for signals
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Block signals in this thread.
|
|
|
|
// Threads spawned later will inherit the signal mask.
|
|
|
|
sgnl::SignalHandler signal_handler({SIGINT, SIGTERM, SIGUSR1});
|
|
|
|
|
|
|
|
std::future<int> ft_sig_handler =
|
2020-07-18 06:20:54 +08:00
|
|
|
// Spawn a thread that handles the
|
|
|
|
// signals {SIGINT, SIGTERM, SIGUSR1}
|
|
|
|
signal_handler.async_sigwait_handler(my_handler);
|
2019-10-13 21:06:50 +08:00
|
|
|
|
|
|
|
std::vector<std::future<void>> futures;
|
|
|
|
for(int i = 0; i < 10; ++i)
|
|
|
|
futures.push_back(
|
|
|
|
std::async(
|
|
|
|
std::launch::async,
|
|
|
|
Worker,
|
|
|
|
std::ref(exit_condition)));
|
|
|
|
|
|
|
|
// SIGUSR1
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
2020-08-01 08:05:43 +08:00
|
|
|
kill(getpid(), SIGUSR1);
|
2019-10-13 21:06:50 +08:00
|
|
|
|
|
|
|
// SIGTERM
|
2020-08-01 08:05:43 +08:00
|
|
|
kill(getpid(), SIGTERM);
|
2019-10-13 21:06:50 +08:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
|
|
|
|
|
for(auto& future : futures)
|
|
|
|
future.wait();
|
|
|
|
|
|
|
|
int last_signal = ft_sig_handler.get();
|
|
|
|
std::cout << "exiting (received signal " << last_signal << ")\n";
|
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
|
|
|
|