diff --git a/examples/benchmarks/sph_weak_scale_test.py b/examples/benchmarks/sph_weak_scale_test.py index 2c3f7f5336..a29327ed5c 100644 --- a/examples/benchmarks/sph_weak_scale_test.py +++ b/examples/benchmarks/sph_weak_scale_test.py @@ -80,9 +80,9 @@ setup.apply_setup( gen, gen_step=int(scheduler_split_val / 8), - insert_step=int(scheduler_split_val * 2), + insert_step=int(scheduler_split_val / 4), msg_count_limit=1024, - rank_comm_size_limit=int(scheduler_split_val) * 2, + rank_comm_size_limit=int(scheduler_split_val), max_msg_size=int(scheduler_split_val / 8), do_setup_log=False, ) diff --git a/src/shamalgs/include/shamalgs/serialize.hpp b/src/shamalgs/include/shamalgs/serialize.hpp index 40669e7972..8e4b15bf6a 100644 --- a/src/shamalgs/include/shamalgs/serialize.hpp +++ b/src/shamalgs/include/shamalgs/serialize.hpp @@ -343,18 +343,52 @@ namespace shamalgs { template inline void write_buf(sham::DeviceBuffer &buf, u64 len) { - StackEntry stack_loc{false}; + __shamrock_stack_entry(); + + /* + std::string info + = shambase::format("write_buf: len={}, buf.get_size()={}", len, buf.get_size()); + + [[maybe_unused]] StackEntry __shamrock_unique_name(stack_loc_){ + false, SourceLocation{info}}; +*/ using Helper = details::SerializeHelperMember; u64 current_head = head_device; u64 offset = align_repr(len * Helper::szrepr); check_head_move_device(offset, len); + /* + info = shambase::format( + "write_buf: len={}, buf.get_size()={}, current_head={}, offset={}", + len, + buf.get_size(), + current_head, + offset); + + [[maybe_unused]] StackEntry __shamrock_unique_name(stack_loc_){ + false, SourceLocation{info}}; +*/ sham::EventList depends_list; const T *accbuf = buf.get_read_access(depends_list); auto accbufbyte = storage.get_write_access(depends_list); + /* + info = shambase::format( + "write_buf: len={}, buf.get_size()={}, current_head={}, offset={}, " + "depends_list.size()={}, accbuf={}, accbufbyte={}", + len, + buf.get_size(), + current_head, + offset, + depends_list.get_events().size(), + static_cast(accbuf), + static_cast(accbufbyte)); + + [[maybe_unused]] StackEntry __shamrock_unique_name(stack_loc_){ + false, SourceLocation{info}}; +*/ auto e = dev_sched->get_queue().submit( depends_list, [&, current_head](sycl::handler &cgh) { cgh.parallel_for(sycl::range<1>{len}, [=](sycl::item<1> id) { @@ -363,22 +397,51 @@ namespace shamalgs { }); }); + // [[maybe_unused]] StackEntry __shamrock_unique_name(stack_loc_){ + // false, SourceLocation{info}}; + buf.complete_event_state(e); storage.complete_event_state(e); head_device += offset; + + // [[maybe_unused]] StackEntry __shamrock_unique_name(stack_loc_){ + // false, SourceLocation{info}}; } template inline void load_buf(sham::DeviceBuffer &buf, u64 len) { - StackEntry stack_loc{false}; + __shamrock_stack_entry(); + + /* + std::string info = shambase::format( + "load_buf: len={}, buf.get_size()={} head_device={}", + len, + buf.get_size(), + head_device); + + [[maybe_unused]] StackEntry __shamrock_unique_name(stack_loc_){ + false, SourceLocation{info}}; +*/ using Helper = details::SerializeHelperMember; u64 current_head = head_device; u64 offset = align_repr(len * Helper::szrepr); check_head_move_device(offset, len); + /* + info = shambase::format( + "load_buf: len={}, buf.get_size()={}, current_head={}, offset={} head_device={}", + len, + buf.get_size(), + current_head, + offset, + head_device); + + [[maybe_unused]] StackEntry __shamrock_unique_name(stack_loc_){ + false, SourceLocation{info}}; +*/ if (buf.get_size() < len) { shambase::throw_with_loc(shambase::format( "SerializeHelper::load_buf: (buf.get_size() < len)\n buf.get_size()={}\n " @@ -391,6 +454,22 @@ namespace shamalgs { T *accbuf = buf.get_write_access(depends_list); auto accbufbyte = storage.get_read_access(depends_list); + /* + info = shambase::format( + "load_buf: len={}, buf.get_size()={}, current_head={}, offset={}, " + "depends_list.size()={}, accbuf={}, accbufbyte={} head_device={}", + len, + buf.get_size(), + current_head, + offset, + depends_list.get_events().size(), + static_cast(accbuf), + static_cast(accbufbyte), + head_device); + + [[maybe_unused]] StackEntry __shamrock_unique_name(stack_loc_){ + false, SourceLocation{info}}; +*/ auto e = dev_sched->get_queue().submit( depends_list, [&, current_head](sycl::handler &cgh) { cgh.parallel_for(sycl::range<1>{len}, [=](sycl::item<1> id) { @@ -398,11 +477,31 @@ namespace shamalgs { accbuf[id] = Helper::load(&accbufbyte[head]); }); }); - + /* + [[maybe_unused]] StackEntry __shamrock_unique_name(stack_loc_){ + false, SourceLocation{info}}; + */ buf.complete_event_state(e); storage.complete_event_state(e); head_device += offset; + + /* + info = shambase::format( + "load_buf: len={}, buf.get_size()={}, current_head={}, offset={}, " + "depends_list.size()={}, accbuf={}, accbufbyte={} head_device={}", + len, + buf.get_size(), + current_head, + offset, + depends_list.get_events().size(), + static_cast(accbuf), + static_cast(accbufbyte), + head_device); + + [[maybe_unused]] StackEntry __shamrock_unique_name(stack_loc_){ + false, SourceLocation{info}}; + */ } }; diff --git a/src/shambackends/include/shambackends/DeviceBuffer.hpp b/src/shambackends/include/shambackends/DeviceBuffer.hpp index 6bf7ad6efe..d2bd429c31 100644 --- a/src/shambackends/include/shambackends/DeviceBuffer.hpp +++ b/src/shambackends/include/shambackends/DeviceBuffer.hpp @@ -75,7 +75,7 @@ namespace sham { inline sham::EventList safe_fill_lambda( sham::DeviceQueue &q, sham::EventList &depends_list, T *dest, size_t count, Fct &&fct) { __shamrock_stack_entry(); - u64 max_copy_len = (1 << 30); // 1G elements, this garanteee indexing below i32_max + u64 max_copy_len = (1 << 30) / sizeof(T); // 1GB sham::EventList events; diff --git a/src/shambackends/include/shambackends/DeviceQueue.hpp b/src/shambackends/include/shambackends/DeviceQueue.hpp index 1fc01c3c63..c324fc6f7f 100644 --- a/src/shambackends/include/shambackends/DeviceQueue.hpp +++ b/src/shambackends/include/shambackends/DeviceQueue.hpp @@ -100,17 +100,32 @@ namespace sham { template sycl::event submit(Fct &&fct) { + __shamrock_stack_entry(); + + wait_and_throw(); + auto e = q.submit([&](sycl::handler &h) { fct(h); }); if (wait_after_submit) { + __shamrock_stack_entry(); e.wait_and_throw(); } return e; } + /** + * @brief Wait for the queue to finish and throw an exception if one has occurred + * + * This function waits for the queue to finish and throws an exception if one has occurred. + */ + void wait_and_throw() { + __shamrock_stack_entry(); + q.wait_and_throw(); + } + /** * @brief Submits a kernel to the SYCL queue, adding the events in the * provided EventList as dependencies @@ -138,14 +153,18 @@ namespace sham { template sycl::event submit(EventList &elist, Fct &&fct) { - elist.consumed = true; + __shamrock_stack_entry(); - auto e = q.submit([&](sycl::handler &h) { + wait_and_throw(); + + elist.consumed = true; + auto e = q.submit([&](sycl::handler &h) { elist.apply_dependancy(h); fct(h); }); if (wait_after_submit) { + __shamrock_stack_entry(); e.wait_and_throw(); } diff --git a/src/shambackends/src/Device.cpp b/src/shambackends/src/Device.cpp index 6a15210e38..3371a21c5f 100644 --- a/src/shambackends/src/Device.cpp +++ b/src/shambackends/src/Device.cpp @@ -88,10 +88,6 @@ namespace sham { try { \ return {dev.get_info()}; \ } catch (...) { \ - logger::warn_ln( \ - "Device", \ - "dev.get_info() raised an exception for device", \ - name); \ return {}; \ } \ }(); @@ -102,10 +98,6 @@ namespace sham { try { \ return {dev.get_info()}; \ } catch (...) { \ - logger::warn_ln( \ - "Device", \ - "dev.get_info() raised an exception for device", \ - name); \ return {}; \ } \ }(); @@ -116,8 +108,6 @@ namespace sham { try { \ return {dev.get_info()}; \ } catch (...) { \ - logger::warn_ln( \ - "Device", "dev.get_info<" #info_ ">() raised an exception for device", name); \ return {}; \ } \ }(); diff --git a/src/shambase/include/shambase/SourceLocation.hpp b/src/shambase/include/shambase/SourceLocation.hpp index a414191ef0..2f9a234126 100644 --- a/src/shambase/include/shambase/SourceLocation.hpp +++ b/src/shambase/include/shambase/SourceLocation.hpp @@ -17,6 +17,7 @@ */ #include "shambase/source_location.hpp" +#include #include /** @@ -32,8 +33,11 @@ struct SourceLocation { using srcloc = shambase::cxxstd::source_location; srcloc loc; + std::optional message; - inline explicit SourceLocation(srcloc _loc = srcloc::current()) : loc(_loc) {} + inline explicit SourceLocation( + std::optional _message = std::nullopt, srcloc _loc = srcloc::current()) + : loc(_loc), message(_message) {} /** * @brief format the location in multiple lines diff --git a/src/shambase/src/SourceLocation.cpp b/src/shambase/src/SourceLocation.cpp index e6b2bb86e0..fcf969da10 100644 --- a/src/shambase/src/SourceLocation.cpp +++ b/src/shambase/src/SourceLocation.cpp @@ -56,6 +56,16 @@ std::string SourceLocation::format_one_line() const { } std::string SourceLocation::format_one_line_func() const { - return fmt::format( - "{} ({}:{}:{})", loc.function_name(), loc.file_name(), loc.line(), loc.column()); + if (message.has_value()) { + return fmt::format( + "{} ({}:{}:{}) info={}", + loc.function_name(), + loc.file_name(), + loc.line(), + loc.column(), + message.value()); + } else { + return fmt::format( + "{} ({}:{}:{})", loc.function_name(), loc.file_name(), loc.line(), loc.column()); + } } diff --git a/src/shammodels/sph/include/shammodels/sph/modules/setup/GeneratorLatticeHCP.hpp b/src/shammodels/sph/include/shammodels/sph/modules/setup/GeneratorLatticeHCP.hpp index dcaa600361..9237e34626 100644 --- a/src/shammodels/sph/include/shammodels/sph/modules/setup/GeneratorLatticeHCP.hpp +++ b/src/shammodels/sph/include/shammodels/sph/modules/setup/GeneratorLatticeHCP.hpp @@ -25,6 +25,22 @@ namespace shammodels::sph::modules { + namespace { + void sync_point(SourceLocation loc = SourceLocation{}) { + shamcomm::mpi::Barrier(MPI_COMM_WORLD); + auto dev_sched = shamsys::instance::get_compute_scheduler_ptr(); + auto &q = shambase::get_check_ref(dev_sched).get_queue(); + q.wait_and_throw(); + shamcomm::mpi::Barrier(MPI_COMM_WORLD); + + if (shamcomm::world_rank() == 0) { + logger::raw_ln("sync point", loc.format_one_line()); + } + + shamcomm::mpi::Barrier(MPI_COMM_WORLD); + } + } // namespace + template class GeneratorLatticeHCP : public ISPHSetupNode { using Tscal = shambase::VecComponent; @@ -78,9 +94,14 @@ namespace shammodels::sph::modules { "total", skip_start + gen_cnt + skip_end); + sync_point(); + generator.skip(skip_start); + sync_point(); auto tmp = generator.next_n(gen_cnt); + sync_point(); generator.skip(skip_end); + sync_point(); for (Tvec r : tmp) { if (Patch::is_in_patch_converted(r, box.lower, box.upper)) { @@ -91,24 +112,33 @@ namespace shammodels::sph::modules { // Make a patchdata from pos_data PatchDataLayer tmp(sched.get_layout_ptr_old()); + sync_point(); if (!pos_data.empty()) { tmp.resize(pos_data.size()); + } + sync_point(); + if (!pos_data.empty()) { tmp.fields_raz(); + } + sync_point(); - { - u32 len = pos_data.size(); - PatchDataField &f - = tmp.get_field(sched.pdl_old().get_field_idx("xyz")); - // sycl::buffer buf(pos_data.data(), len); - f.override(pos_data, len); - } + if (!pos_data.empty()) { + u32 len = pos_data.size(); + PatchDataField &f + = tmp.get_field(sched.pdl_old().get_field_idx("xyz")); + // sycl::buffer buf(pos_data.data(), len); + f.override(pos_data, len); + } + sync_point(); - { - PatchDataField &f - = tmp.get_field(sched.pdl_old().get_field_idx("hpart")); - f.override(dr); - } + if (!pos_data.empty()) { + PatchDataField &f + = tmp.get_field(sched.pdl_old().get_field_idx("hpart")); + f.override(dr); } + + sync_point(); + return tmp; } diff --git a/src/shammodels/sph/src/modules/SPHSetup.cpp b/src/shammodels/sph/src/modules/SPHSetup.cpp index 44c0e3af8f..3eb6b9051a 100644 --- a/src/shammodels/sph/src/modules/SPHSetup.cpp +++ b/src/shammodels/sph/src/modules/SPHSetup.cpp @@ -251,6 +251,22 @@ struct SetupLog { inline constexpr f64 golden_number = 1.61803398874989484820458683436563; +namespace { + void sync_point(SourceLocation loc = SourceLocation{}) { + shamcomm::mpi::Barrier(MPI_COMM_WORLD); + auto dev_sched = shamsys::instance::get_compute_scheduler_ptr(); + auto &q = shambase::get_check_ref(dev_sched).get_queue(); + q.wait_and_throw(); + shamcomm::mpi::Barrier(MPI_COMM_WORLD); + + if (shamcomm::world_rank() == 0) { + logger::raw_ln("sync point", loc.format_one_line()); + } + + shamcomm::mpi::Barrier(MPI_COMM_WORLD); + } +} // namespace + template class SPHKernel> void shammodels::sph::modules::SPHSetup::apply_setup_new( SetupNodePtr setup, @@ -264,6 +280,8 @@ void shammodels::sph::modules::SPHSetup::apply_setup_new( __shamrock_stack_entry(); + sync_point(); + if (!bool(setup)) { shambase::throw_with_loc("The setup shared pointer is empty"); } @@ -326,8 +344,11 @@ void shammodels::sph::modules::SPHSetup::apply_setup_new( shambase::Timer timer_gen; timer_gen.start(); + sync_point(); shamrock::patch::PatchDataLayer tmp = setup->next_n(gen_step); + sync_point(); + if (solver_config.track_particles_id) { // This bit set the tracking id of the particles // But be carefull this assume that the particle injection order @@ -367,8 +388,10 @@ void shammodels::sph::modules::SPHSetup::apply_setup_new( .overwrite(part_ids, loc_inj); } } + sync_point(); to_insert.insert_elements(tmp); + sync_point(); u64 sum_push = shamalgs::collective::allreduce_sum(tmp.get_obj_cnt()); u64 sum_all = shamalgs::collective::allreduce_sum(to_insert.get_obj_cnt()); @@ -416,6 +439,7 @@ void shammodels::sph::modules::SPHSetup::apply_setup_new( time_part_inject.start(); auto log_inject_status = [&](std::string log_suffix = "") { + __shamrock_stack_entry(); u64 sum_all = shamalgs::collective::allreduce_sum(to_insert.get_obj_cnt()); u32 rank_without_patch @@ -523,6 +547,14 @@ void shammodels::sph::modules::SPHSetup::apply_setup_new( err_id_in_newid = err_id_in_newid || (err); i32 rank = sched.get_patch_rank_owner(patch_id); + + if (rank >= shamcomm::world_size() || rank < 0) { + throw shambase::make_except_with_loc(shambase::format( + "rank is out of bounds: rank = {}, world size = {}", + rank, + shamcomm::world_size())); + } + index_per_ranks[rank].push_back(i); } } @@ -545,6 +577,8 @@ void shammodels::sph::modules::SPHSetup::apply_setup_new( u32 step_count = 0; while (!shamalgs::collective::are_all_rank_true(to_insert.is_empty(), MPI_COMM_WORLD)) { + __shamrock_stack_entry(); + // assume that the sched is synchronized and that there is at least a patch. // TODO actually check that @@ -554,12 +588,16 @@ void shammodels::sph::modules::SPHSetup::apply_setup_new( inject_in_local_domains(to_insert); + __shamrock_stack_entry(); + f64 timer_get_index_per_ranks = 0; std::unordered_map> index_per_ranks = get_index_per_ranks(timer_get_index_per_ranks); total_time_rank_getter += timer_get_index_per_ranks; max_time_rank_getter = std::max(max_time_rank_getter, timer_get_index_per_ranks); + __shamrock_stack_entry(); + // allgather the list of messages // format:(u32_2(sender_rank, receiver_rank), u64(indices_size)) std::vector send_msg; @@ -568,6 +606,8 @@ void shammodels::sph::modules::SPHSetup::apply_setup_new( send_msg.push_back(indices.size()); } + __shamrock_stack_entry(); + u64 max_send = (1 << 24) / shamcomm::world_size(); bool sync_limited = false; if (send_msg.size() > max_send) { @@ -606,6 +646,8 @@ void shammodels::sph::modules::SPHSetup::apply_setup_new( sync_limited = true; } + __shamrock_stack_entry(); + std::vector recv_msg; shamalgs::collective::vector_allgatherv(send_msg, recv_msg, MPI_COMM_WORLD); @@ -617,6 +659,19 @@ void shammodels::sph::modules::SPHSetup::apply_setup_new( u32 sender_rank = sender_receiver.x(); u32 receiver_rank = sender_receiver.y(); + if (receiver_rank >= shamcomm::world_size() || receiver_rank < 0) { + throw shambase::make_except_with_loc(shambase::format( + "receiver rank is out of bounds: rank = {}, world size = {}", + receiver_rank, + shamcomm::world_size())); + } + if (sender_rank >= shamcomm::world_size() || sender_rank < 0) { + throw shambase::make_except_with_loc(shambase::format( + "sender rank is out of bounds: rank = {}, world size = {}", + sender_rank, + shamcomm::world_size())); + } + if (sender_rank == receiver_rank) { continue; // only mean that it was not fully inserted in the patch } @@ -628,10 +683,14 @@ void shammodels::sph::modules::SPHSetup::apply_setup_new( setup_log.value().update_msg_list(msg_list); } + __shamrock_stack_entry(); + // shuffle msg_list according to seed golden_number*1000*step_count std::mt19937 eng_global_msg(u64(golden_number * 1000 * step_count)); std::shuffle(msg_list.begin(), msg_list.end(), eng_global_msg); + __shamrock_stack_entry(); + // now that we are in sync we can determine who should send to who std::vector msg_count_rank(shamcomm::world_size()); @@ -676,6 +735,8 @@ void shammodels::sph::modules::SPHSetup::apply_setup_new( comm_size_rank.at(sender_rank) += msg_size; } + __shamrock_stack_entry(); + // logger::raw_ln( // shamcomm::world_rank(), // was_count_limited, @@ -708,8 +769,12 @@ void shammodels::sph::modules::SPHSetup::apply_setup_new( } } + __shamrock_stack_entry(); + to_insert.remove_ids(idx_to_rem, idx_to_rem.get_size()); + __shamrock_stack_entry(); + // comm the data to the right ranks shambase::DistributedDataShared recv_dat; @@ -734,11 +799,15 @@ void shammodels::sph::modules::SPHSetup::apply_setup_new( }, comm_cache); + __shamrock_stack_entry(); + // insert the data into the data to be inserted recv_dat.for_each([&](u64 sender, u64 receiver, PatchDataLayer &pdat) { to_insert.insert_elements(pdat); }); + __shamrock_stack_entry(); + was_count_limited = !shamalgs::collective::are_all_rank_true(!was_count_limited, MPI_COMM_WORLD); was_size_limited diff --git a/src/shamrock/src/scheduler/SchedulerPatchData.cpp b/src/shamrock/src/scheduler/SchedulerPatchData.cpp index 288ff19683..f325690cf8 100644 --- a/src/shamrock/src/scheduler/SchedulerPatchData.cpp +++ b/src/shamrock/src/scheduler/SchedulerPatchData.cpp @@ -18,6 +18,7 @@ #include "shambase/narrowing.hpp" #include "shambase/string.hpp" #include "shambackends/comm/CommunicationBuffer.hpp" +#include "shamcomm/logs.hpp" #include "shamrock/patch/PatchDataField.hpp" #include "shamrock/patch/PatchDataLayerLayout.hpp" #include "shamrock/scheduler/HilbertLoadBalance.hpp" @@ -88,7 +89,7 @@ namespace shamrock::scheduler { shamcomm::mpi::Irecv( msg.buf->get_ptr(), - cnt, + shambase::narrow_or_throw(cnt), get_mpi_type(), msg.rank, msg.tag, @@ -106,6 +107,7 @@ namespace shamrock::scheduler { using ChangeOp = shamrock::scheduler::LoadBalancingChangeList::ChangeOp; auto serializer = [](shamrock::patch::PatchDataLayer &pdat) { + __shamrock_stack_entry(); shamalgs::SerializeHelper ser(shamsys::instance::get_compute_scheduler_ptr()); ser.allocate(pdat.serialize_buf_byte_size()); pdat.serialize_buf(ser); @@ -113,6 +115,7 @@ namespace shamrock::scheduler { }; auto deserializer = [&](sham::DeviceBuffer &&buf) { + __shamrock_stack_entry(); // exchange the buffer held by the distrib data and give it to the serializer shamalgs::SerializeHelper ser( shamsys::instance::get_compute_scheduler_ptr(), @@ -122,6 +125,7 @@ namespace shamrock::scheduler { std::vector send_payloads; for (const ChangeOp op : change_list.change_ops) { + __shamrock_stack_entry(); // if i'm sender if (op.rank_owner_old == shamcomm::world_rank()) { auto &patchdata = owned_data.get(op.patch_id); @@ -142,6 +146,7 @@ namespace shamrock::scheduler { std::vector recv_payloads; for (const ChangeOp op : change_list.change_ops) { + __shamrock_stack_entry(); auto &id_patch = op.patch_id; // if i'm receiver @@ -163,6 +168,7 @@ namespace shamrock::scheduler { u32 idx = 0; // receive for (const ChangeOp op : change_list.change_ops) { + __shamrock_stack_entry(); auto &id_patch = op.patch_id; // if i'm receiver @@ -182,6 +188,7 @@ namespace shamrock::scheduler { // erase old patchdata for (const ChangeOp op : change_list.change_ops) { + __shamrock_stack_entry(); auto &id_patch = op.patch_id; patch_list.global[op.patch_idx].node_owner_id = op.rank_owner_new; diff --git a/src/shamsys/src/SignalCatch.cpp b/src/shamsys/src/SignalCatch.cpp index 7918ba83d8..92a68ed789 100644 --- a/src/shamsys/src/SignalCatch.cpp +++ b/src/shamsys/src/SignalCatch.cpp @@ -21,16 +21,68 @@ #include namespace shamsys::details { - void signal_callback_handler(int signum) { + /** + * @brief Name the received signal + * @note List made from and . + * @param signum The signal number + * @return const char* The name of the signal + */ + const char *get_signal_name(int signum) { const char *signame = nullptr; switch (signum) { - case SIGTERM: signame = "SIGTERM"; break; + + // ISO C99 signals. case SIGINT : signame = "SIGINT"; break; + case SIGILL : signame = "SIGILL"; break; + case SIGABRT: signame = "SIGABRT"; break; + case SIGFPE : signame = "SIGFPE"; break; case SIGSEGV: signame = "SIGSEGV"; break; - case SIGIOT : signame = "SIGIOT"; break; - default : signame = "UNKNOWN"; break; + case SIGTERM: signame = "SIGTERM"; break; + + // Historical signals specified by POSIX. + case SIGHUP : signame = "SIGHUP"; break; + case SIGQUIT: signame = "SIGQUIT"; break; + case SIGTRAP: signame = "SIGTRAP"; break; + case SIGKILL: signame = "SIGKILL"; break; + case SIGPIPE: signame = "SIGPIPE"; break; + case SIGALRM: signame = "SIGALRM"; break; + + // Adjustments and additions to the signal number constants for most Linux systems. + case SIGSTKFLT: signame = "SIGSTKFLT"; break; + case SIGPWR : signame = "SIGPWR"; break; + + // Historical signals specified by POSIX. + case SIGBUS: signame = "SIGBUS"; break; + case SIGSYS: signame = "SIGSYS"; break; + + // New(er) POSIX signals (1003.1-2008, 1003.1-2013). + case SIGURG : signame = "SIGURG"; break; + case SIGSTOP : signame = "SIGSTOP"; break; + case SIGTSTP : signame = "SIGTSTP"; break; + case SIGCONT : signame = "SIGCONT"; break; + case SIGCHLD : signame = "SIGCHLD"; break; + case SIGTTIN : signame = "SIGTTIN"; break; + case SIGTTOU : signame = "SIGTTOU"; break; + case SIGPOLL : signame = "SIGPOLL"; break; + case SIGXFSZ : signame = "SIGXFSZ"; break; + case SIGXCPU : signame = "SIGXCPU"; break; + case SIGVTALRM: signame = "SIGVTALRM"; break; + case SIGPROF : signame = "SIGPROF"; break; + case SIGUSR1 : signame = "SIGUSR1"; break; + case SIGUSR2 : signame = "SIGUSR2"; break; + + // Nonstandard signals found in all modern POSIX systems (including both BSD and Linux). + case SIGWINCH: signame = "SIGWINCH"; break; + + default: signame = "UNKNOWN"; break; } + return signame; + } + + void signal_callback_handler(int signum) { + + const char *signame = get_signal_name(signum); // ensure that we print in one block to avoid interleaving std::string log = fmt::format(