Skip to content

Signals

Signals

Signals might be important to properly stop asynchronous operations, such as servers.

Boost.Asio supports signal handling using a class called signal_set. Programs may add one or more signals to the set, and then perform an async_wait() operation.

The specified handler will be called when one of the signals occurs. The same signal number may be registered with multiple signal_set objects, however the signal number must be used only with Boost.Asio.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
find_package(Asio 1.21.0 QUIET)
if (NOT Asio_FOUND)
    FetchContent_Declare(asio GIT_REPOSITORY https://github.com/chriskohlhoff/asio.git GIT_TAG asio-1-21-0)
    FetchContent_GetProperties(asio)
    if (NOT asio_POPULATED)
        FetchContent_Populate(asio)
        add_library(asio INTERFACE)
        target_include_directories(asio INTERFACE ${asio_SOURCE_DIR}/asio/include)
        target_compile_definitions(asio INTERFACE ASIO_STANDALONE ASIO_NO_DEPRECATED)
        target_link_libraries(asio INTERFACE Threads::Threads)
    endif ()
endif()

1
2
add_executable(signals signals.cpp)
target_link_libraries(signals asio)

1
asio::io_context io_context;

1
asio::signal_set signals(io_context, SIGINT, SIGTERM);

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// The signals will set stop_timer to true
std::atomic<bool> request_stop_timer = false;
signals.async_wait([&](const asio::error_code &ec, int signal_number) {
    if (!ec) {
        std::cout << "Signal number " << signal_number << std::endl;
        std::cout << "Gracefully stopping the timer and exiting"
                  << std::endl;
        request_stop_timer.store(true);
    } else {
        std::cout << "Error " << ec.value() << " - " << ec.message()
                  << " - Signal number - " << signal_number << std::endl;
    }
});

1
asio::steady_timer t(io_context, asio::chrono::seconds(1));

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
int count = 0;
std::function<void(asio::error_code)> timer_callback;
timer_callback = [&](asio::error_code ec) {
    if (!ec) {
        if (count < 30 && !request_stop_timer.load()) {
            // Increase counter
            std::cout << count << std::endl;
            ++count;
            // Set the timer again
            t.expires_at(t.expiry() + std::chrono::seconds(1));
            t.async_wait(timer_callback);
        } else {
            std::cout << "Reached " << count << std::endl;
        }
    } else {
        std::cout << "Timer Error" << std::endl;
    }
};

1
t.async_wait(timer_callback);

1
2
3
4
asio::thread_pool pool;
for (size_t i = 0; i < std::thread::hardware_concurrency(); ++i) {
    asio::post(pool, [&io_context] { io_context.run(); });
}

Share Snippets