/src/libzmq/src/reaper.cpp
Line | Count | Source |
1 | | /* SPDX-License-Identifier: MPL-2.0 */ |
2 | | |
3 | | #include "precompiled.hpp" |
4 | | #include "macros.hpp" |
5 | | #include <new> |
6 | | #include "reaper.hpp" |
7 | | #include "socket_base.hpp" |
8 | | #include "err.hpp" |
9 | | |
10 | | zmq::reaper_t::reaper_t (class ctx_t *ctx_, uint32_t tid_) : |
11 | 0 | object_t (ctx_, tid_), |
12 | 0 | _mailbox_handle (static_cast<poller_t::handle_t> (NULL)), |
13 | 0 | _poller (NULL), |
14 | 0 | _sockets (0), |
15 | 0 | _terminating (false) |
16 | 0 | { |
17 | 0 | if (!_mailbox.valid ()) |
18 | 0 | return; |
19 | | |
20 | 0 | _poller = new (std::nothrow) poller_t (*ctx_); |
21 | 0 | alloc_assert (_poller); |
22 | |
|
23 | 0 | if (_mailbox.get_fd () != retired_fd) { |
24 | 0 | _mailbox_handle = _poller->add_fd (_mailbox.get_fd (), this); |
25 | 0 | _poller->set_pollin (_mailbox_handle); |
26 | 0 | } |
27 | |
|
28 | 0 | #ifdef HAVE_FORK |
29 | 0 | _pid = getpid (); |
30 | 0 | #endif |
31 | 0 | } |
32 | | |
33 | | zmq::reaper_t::~reaper_t () |
34 | 0 | { |
35 | 0 | LIBZMQ_DELETE (_poller); |
36 | 0 | } |
37 | | |
38 | | zmq::mailbox_t *zmq::reaper_t::get_mailbox () |
39 | 0 | { |
40 | 0 | return &_mailbox; |
41 | 0 | } |
42 | | |
43 | | void zmq::reaper_t::start () |
44 | 0 | { |
45 | 0 | zmq_assert (_mailbox.valid ()); |
46 | | |
47 | | // Start the thread. |
48 | 0 | _poller->start ("Reaper"); |
49 | 0 | } |
50 | | |
51 | | void zmq::reaper_t::stop () |
52 | 0 | { |
53 | 0 | if (get_mailbox ()->valid ()) { |
54 | 0 | send_stop (); |
55 | 0 | } |
56 | 0 | } |
57 | | |
58 | | void zmq::reaper_t::in_event () |
59 | 0 | { |
60 | 0 | while (true) { |
61 | 0 | #ifdef HAVE_FORK |
62 | 0 | if (unlikely (_pid != getpid ())) { |
63 | | //printf("zmq::reaper_t::in_event return in child process %d\n", (int)getpid()); |
64 | 0 | return; |
65 | 0 | } |
66 | 0 | #endif |
67 | | |
68 | | // Get the next command. If there is none, exit. |
69 | 0 | command_t cmd; |
70 | 0 | const int rc = _mailbox.recv (&cmd, 0); |
71 | 0 | if (rc != 0 && errno == EINTR) |
72 | 0 | continue; |
73 | 0 | if (rc != 0 && errno == EAGAIN) |
74 | 0 | break; |
75 | 0 | errno_assert (rc == 0); |
76 | | |
77 | | // Process the command. |
78 | 0 | cmd.destination->process_command (cmd); |
79 | 0 | } |
80 | 0 | } |
81 | | |
82 | | void zmq::reaper_t::out_event () |
83 | 0 | { |
84 | 0 | zmq_assert (false); |
85 | 0 | } |
86 | | |
87 | | void zmq::reaper_t::timer_event (int) |
88 | 0 | { |
89 | 0 | zmq_assert (false); |
90 | 0 | } |
91 | | |
92 | | void zmq::reaper_t::process_stop () |
93 | 0 | { |
94 | 0 | _terminating = true; |
95 | | |
96 | | // If there are no sockets being reaped finish immediately. |
97 | 0 | if (!_sockets) { |
98 | 0 | send_done (); |
99 | 0 | _poller->rm_fd (_mailbox_handle); |
100 | 0 | _poller->stop (); |
101 | 0 | } |
102 | 0 | } |
103 | | |
104 | | void zmq::reaper_t::process_reap (socket_base_t *socket_) |
105 | 0 | { |
106 | | // Add the socket to the poller. |
107 | 0 | socket_->start_reaping (_poller); |
108 | |
|
109 | 0 | ++_sockets; |
110 | 0 | } |
111 | | |
112 | | void zmq::reaper_t::process_reaped () |
113 | 0 | { |
114 | 0 | --_sockets; |
115 | | |
116 | | // If reaped was already asked to terminate and there are no more sockets, |
117 | | // finish immediately. |
118 | 0 | if (!_sockets && _terminating) { |
119 | 0 | send_done (); |
120 | 0 | _poller->rm_fd (_mailbox_handle); |
121 | 0 | _poller->stop (); |
122 | 0 | } |
123 | 0 | } |