xref: /openbmc/sdeventplus/src/sdeventplus/source/child.hpp (revision a8c11e3ca342b090aec615c832b85686bd4655f6)
1 #pragma once
2 
3 #include <signal.h>
4 
5 #include <function2/function2.hpp>
6 #include <sdeventplus/source/base.hpp>
7 #include <sdeventplus/types.hpp>
8 
9 namespace sdeventplus
10 {
11 namespace source
12 {
13 
14 namespace detail
15 {
16 class ChildData;
17 } // namespace detail
18 
19 /** @class Child
20  *  @brief A wrapper around the sd_event_source child type
21  *         See sd_event_add_child(3) for more information
22  */
23 class Child : public Base
24 {
25   public:
26     using Callback =
27         fu2::unique_function<void(Child& source, const siginfo_t* si)>;
28 
29     /** @brief Adds a new child source handler to the Event
30      *         This type of source defaults to Enabled::Oneshot, and needs to be
31      *         reconfigured upon each callback.
32      *
33      *  @param[in] event    - The event to attach the handler
34      *  @param[in] pid      - The pid of the child to monitor
35      *  @param[in] options  - An OR-ed mask that determines triggers
36      *                        See waitid(2) for further information
37      *  @param[in] callback - The function executed on event dispatch
38      */
39     Child(const Event& event, pid_t pid, int options, Callback&& callback);
40 
41     /** @brief Constructs a non-owning child source handler
42      *         Does not own the passed reference to the source because
43      *         this is meant to be used only as a reference inside an event
44      *         source.
45      *  @internal
46      *
47      *  @param[in] other - The source wrapper to copy
48      *  @param[in]       - Signifies that this new copy is non-owning
49      */
50     Child(const Child& other, sdeventplus::internal::NoOwn);
51 
52     /** @brief Sets the callback
53      *
54      *  @param[in] callback - The function executed on event dispatch
55      */
56     void set_callback(Callback&& callback);
57 
58     /** @brief Gets the pid of the child process being watched
59      *
60      *  @return The child pid
61      *  @throws SdEventError for underlying sd_event errors
62      */
63     pid_t get_pid() const;
64 
65   private:
66     /** @brief Returns a reference to the source owned child
67      *
68      *  @return A reference to the child
69      */
70     detail::ChildData& get_userdata() const;
71 
72     /** @brief Returns a reference to the callback executed for this source
73      *
74      *  @return A reference to the callback
75      */
76     Callback& get_callback();
77 
78     /** @brief Creates a new child source attached to the Event
79      *
80      *  @param[in] event   - The event to attach the handler
81      *  @param[in] pid     - The pid of the child to monitor
82      *  @param[in] options - An OR-ed mask that determines triggers
83      *  @throws SdEventError for underlying sd_event errors
84      *  @return A new sd_event_source
85      */
86     static sd_event_source* create_source(const Event& event, pid_t pid,
87                                           int options);
88 
89     /** @brief A wrapper around the callback that can be called from sd-event
90      *
91      *  @param[in] source   - The sd_event_source associated with the call
92      *  @param[in] userdata - The provided userdata for the source
93      *  @return 0 on success or a negative errno otherwise
94      */
95     static int childCallback(sd_event_source* source, const siginfo_t* si,
96                              void* userdata);
97 };
98 
99 namespace detail
100 {
101 
102 class ChildData : public Child, public BaseData
103 {
104   private:
105     Child::Callback callback;
106 
107   public:
108     ChildData(const Child& base, Child::Callback&& callback);
109 
110     friend Child;
111 };
112 
113 } // namespace detail
114 
115 } // namespace source
116 } // namespace sdeventplus
117