1 #pragma once
2 
3 #include <sys/signalfd.h>
4 
5 #include <function2/function2.hpp>
6 #include <sdeventplus/event.hpp>
7 #include <sdeventplus/source/base.hpp>
8 #include <sdeventplus/types.hpp>
9 
10 namespace sdeventplus
11 {
12 namespace source
13 {
14 
15 namespace detail
16 {
17 class SignalData;
18 } // namespace detail
19 
20 /** @class Signal
21  *  @brief A wrapper around the sd_event_source signal type
22  *         See sd_event_add_signal(3) for more information
23  */
24 class Signal : public Base
25 {
26   public:
27     /** @brief Type of the user provided callback function */
28     using Callback = fu2::unique_function<void(
29         Signal& source, const struct signalfd_siginfo* si)>;
30 
31     /** @brief Creates a new signal event source on the provided event loop
32      *         This type of source defaults to Enabled::On, executing the
33      *         callback for each signal observed. You are required to block
34      *         the signal in all threads prior to creating this source.
35      *
36      *  @param[in] event    - The event to attach the handler
37      *  @param[in] sig      - Signum to watch, see signal(7)
38      *  @param[in] callback - The function executed on event dispatch
39      *  @throws SdEventError for underlying sd_event errors
40      */
41     Signal(const Event& event, int sig, Callback&& callback);
42 
43     /** @brief Constructs a non-owning signal source handler
44      *         Does not own the passed reference to the source because
45      *         this is meant to be used only as a reference inside an event
46      *         source.
47      *  @internal
48      *
49      *  @param[in] other - The source wrapper to copy
50      *  @param[in]       - Signifies that this new copy is non-owning
51      *  @throws SdEventError for underlying sd_event errors
52      */
53     Signal(const Signal& other, sdeventplus::internal::NoOwn);
54 
55     /** @brief Sets the callback
56      *
57      *  @param[in] callback - The function executed on event dispatch
58      */
59     void set_callback(Callback&& callback);
60 
61     /** @brief Gets the signum watched by the source
62      *
63      *  @throws SdEventError for underlying sd_event errors
64      *  @return Integer signum
65      */
66     int get_signal() const;
67 
68   private:
69     /** @brief Returns a reference to the source owned signal
70      *
71      *  @return A reference to the signal
72      */
73     detail::SignalData& get_userdata() const;
74 
75     /** @brief Returns a reference to the callback executed for this source
76      *
77      *  @return A reference to the callback
78      */
79     Callback& get_callback();
80 
81     /** @brief Creates a new signal source attached to the Event
82      *
83      *  @param[in] event    - The event to attach the handler
84      *  @param[in] sig      - Signum to watch, see signal(7)
85      *  @param[in] callback - The function executed on event dispatch
86      *  @throws SdEventError for underlying sd_event errors
87      *  @return A new sd_event_source
88      */
89     static sd_event_source* create_source(const Event& event, int sig);
90 
91     /** @brief A wrapper around the callback that can be called from sd-event
92      *
93      *  @param[in] source   - The sd_event_source associated with the call
94      *  @param[in] userdata - The provided userdata for the source
95      *  @return 0 on success or a negative errno otherwise
96      */
97     static int signalCallback(sd_event_source* source,
98                               const struct signalfd_siginfo* si,
99                               void* userdata);
100 };
101 
102 namespace detail
103 {
104 
105 class SignalData : public Signal, public BaseData
106 {
107   private:
108     Signal::Callback callback;
109 
110   public:
111     SignalData(const Signal& base, Signal::Callback&& callback);
112 
113     friend Signal;
114 };
115 
116 } // namespace detail
117 
118 } // namespace source
119 } // namespace sdeventplus
120