LCOV - code coverage report
Current view: top level - corosio/native/detail/posix - posix_signal.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 3 3
Test Date: 2026-09-25 22:49:29 Functions: 100.0 % 1 1

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2026 Steve Gerbino
       3                 : // Copyright (c) 2026 Michael Vandeberg
       4                 : //
       5                 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       6                 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       7                 : //
       8                 : // Official repository: https://github.com/cppalliance/corosio
       9                 : //
      10                 : 
      11                 : #ifndef BOOST_COROSIO_NATIVE_DETAIL_POSIX_POSIX_SIGNAL_HPP
      12                 : #define BOOST_COROSIO_NATIVE_DETAIL_POSIX_POSIX_SIGNAL_HPP
      13                 : 
      14                 : #include <boost/corosio/detail/platform.hpp>
      15                 : 
      16                 : #if BOOST_COROSIO_POSIX
      17                 : 
      18                 : #include <boost/corosio/detail/config.hpp>
      19                 : #include <boost/corosio/signal_set.hpp>
      20                 : #include <boost/corosio/detail/intrusive.hpp>
      21                 : #include <boost/corosio/detail/scheduler_op.hpp>
      22                 : #include <boost/capy/continuation.hpp>
      23                 : #include <boost/capy/ex/executor_ref.hpp>
      24                 : 
      25                 : #include <coroutine>
      26                 : #include <cstddef>
      27                 : #include <optional>
      28                 : #include <stop_token>
      29                 : #include <system_error>
      30                 : 
      31                 : namespace boost::corosio {
      32                 : 
      33                 : namespace detail {
      34                 : 
      35                 : // Forward declarations
      36                 : class posix_signal_service;
      37                 : 
      38                 : // Maximum signal number supported (NSIG is typically 64 on Linux)
      39                 : enum
      40                 : {
      41                 :     max_signal_number = 64
      42                 : };
      43                 : 
      44                 : // signal_op - pending wait operation
      45                 : 
      46                 : struct signal_op : scheduler_op
      47                 : {
      48                 :     std::coroutine_handle<> h;
      49                 :     capy::continuation cont;
      50                 :     capy::executor_ref d;
      51                 :     std::error_code* ec_out   = nullptr;
      52                 :     int* signal_out           = nullptr;
      53                 :     int signal_number         = 0;
      54                 :     posix_signal_service* svc = nullptr; // For work_finished callback
      55                 : 
      56                 :     void operator()() override;
      57                 :     void destroy() override;
      58                 : };
      59                 : 
      60                 : // signal_registration - per-signal registration tracking
      61                 : 
      62                 : struct signal_registration
      63                 : {
      64                 :     int signal_number                  = 0;
      65                 :     signal_set::flags_t flags          = signal_set::none;
      66                 :     signal_set::implementation* owner  = nullptr;
      67                 :     std::size_t undelivered            = 0;
      68                 :     signal_registration* next_in_table = nullptr;
      69                 :     signal_registration* prev_in_table = nullptr;
      70                 :     signal_registration* next_in_set   = nullptr;
      71                 : };
      72                 : 
      73                 : // posix_signal - per-signal_set implementation
      74                 : 
      75                 : class posix_signal final
      76                 :     : public signal_set::implementation
      77                 :     , public intrusive_list<posix_signal>::node
      78                 : {
      79                 :     friend class posix_signal_service;
      80                 : 
      81                 :     posix_signal_service& svc_;
      82                 :     signal_registration* signals_ = nullptr;
      83                 :     signal_op pending_op_;
      84                 :     bool waiting_   = false;
      85                 :     bool cancelled_ = false;
      86                 : 
      87                 :     /** Routes a stop request into the service's per-operation cancel.
      88                 : 
      89                 :         Deliberately NOT `cancel_wait`: that sets the sticky `cancelled_`
      90                 :         latch, which belongs to `cancel()` and scopes to the whole set. A
      91                 :         stop token scopes to one wait, so a late fire must be a no-op
      92                 :         rather than poisoning the next wait.
      93                 :     */
      94                 :     struct token_canceller
      95                 :     {
      96                 :         posix_signal* self;
      97                 :         void operator()() const noexcept;
      98                 :     };
      99                 : 
     100                 :     /** Armed for the duration of one wait; see wait().
     101                 : 
     102                 :         Never reset while `posix_signal_service::mutex_` is held:
     103                 :         `~stop_callback` blocks until a concurrently running callback
     104                 :         returns, and that callback takes the same mutex.
     105                 :     */
     106                 :     std::optional<std::stop_callback<token_canceller>> stop_cb_;
     107                 : 
     108                 :     /** Set when a stop request arrives for the current wait.
     109                 : 
     110                 :         Closes a lost-wakeup race. The callback is armed before
     111                 :         `start_wait` takes the lock, so a request landing in that window
     112                 :         finds `waiting_ == false` and would otherwise return having done
     113                 :         nothing, leaving `start_wait` to park the wait forever. Every
     114                 :         other op survives this because `coro_op::on_cancel()` defaults to
     115                 :         `request_cancel()`, which sets a persistent flag the completion
     116                 :         decode reads later; this is that flag for the signal path.
     117                 : 
     118                 :         Distinct from `cancelled_` on purpose: `cancelled_` is the sticky
     119                 :         per-set latch `cancel()` owns, this is per-operation.
     120                 :     */
     121                 :     bool token_cancelled_ = false;
     122                 : 
     123                 : public:
     124                 :     explicit posix_signal(posix_signal_service& svc) noexcept;
     125                 : 
     126                 :     std::coroutine_handle<> wait(
     127                 :         std::coroutine_handle<>,
     128                 :         capy::executor_ref,
     129                 :         std::stop_token,
     130                 :         std::error_code*,
     131                 :         int*) override;
     132                 : 
     133                 :     std::error_code add(int signal_number, signal_set::flags_t flags) override;
     134                 :     std::error_code remove(int signal_number) override;
     135                 :     std::error_code clear() override;
     136                 :     void cancel() noexcept override;
     137                 : 
     138                 :     /// Disarm the wait's stop callback. Called before teardown.
     139 HIT         184 :     void disarm_stop() noexcept
     140                 :     {
     141             184 :         stop_cb_.reset();
     142             184 :     }
     143                 : };
     144                 : 
     145                 : } // namespace detail
     146                 : 
     147                 : } // namespace boost::corosio
     148                 : 
     149                 : #endif // BOOST_COROSIO_POSIX
     150                 : 
     151                 : #endif // BOOST_COROSIO_NATIVE_DETAIL_POSIX_POSIX_SIGNAL_HPP
        

Generated by: LCOV version 2.3