-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlistener.cpp
175 lines (143 loc) · 4.77 KB
/
listener.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include <libpdbg.h>
#include <attn/attn_main.hpp>
#include <boost/interprocess/ipc/message_queue.hpp>
#include <cli.hpp>
#include <listener.hpp>
/** @brief openpower-hw-diags message queue name */
static constexpr const char* mq_listener = "openpower-hw-diags-mq";
/** @brief maximum length of command line parameter */
static constexpr int max_command_len = 25;
/** @brief end of command line args message */
static const char* msg_send_end = "999999999999999";
/**
* @brief Start a thread to monitor the attention GPIO
*
* @param i_config Attention handler configuration object
*/
void* threadGpioMon(void* i_config)
{
// Configure and start attention monitor
attn::attnDaemon((attn::Config*)i_config);
pthread_exit(NULL);
}
/** @brief Start a thread to listen for attention handler messages */
void* threadListener(void* i_params)
{
using namespace boost::interprocess;
// remove listener message queue if exists (does not throw)
message_queue::remove(mq_listener);
// thread handle for gpio monitor
pthread_t ptidGpio;
// status of gpio monitor
bool gpioMonEnabled = false;
// create config
attn::Config attnConfig;
// This is the main listener loop. All the above code will be executed
// only once. All other communtication with the attention handler will
// originate from here via the message queue.
do
{
// vector to hold messages sent to listener
std::vector<std::string> messages;
// we will catch any exceptions from thread library
try
{
// create new message queue or open existing
message_queue mq(open_or_create, mq_listener, 1, max_command_len);
// message queue parameters
char buffer[max_command_len + 1];
size_t recvd_size;
unsigned int priority;
// We will continue receiving messages until we receive
// a msg_send_end message to indicate all command line parameters
// have been sent.
do
{
// wait for a message to arrive
mq.receive((void*)&buffer, max_command_len, recvd_size,
priority);
// null terminate message and store
buffer[recvd_size] = '\0';
messages.push_back(buffer);
} while (buffer != std::string(msg_send_end));
messages.pop_back(); // remove msg_send_end message
// convert messages to command line arguments
std::vector<char*> argv;
std::transform(messages.begin(), messages.end(),
std::back_inserter(argv), (char*)data());
int argc = argv.size();
argv.push_back(nullptr);
// stop attention handler daemon?
if (true == getCliOption(argv.data(), argv.data() + argc, "--stop"))
{
message_queue::remove(mq_listener);
break;
}
// parse config options
parseConfig(argv.data(), argv.data() + argc, &attnConfig);
// start attention handler daemon?
if (true ==
getCliOption(argv.data(), argv.data() + argc, "--start"))
{
if (false == gpioMonEnabled)
{
if (0 == pthread_create(&ptidGpio, NULL, &threadGpioMon,
&attnConfig))
{
gpioMonEnabled = true;
}
else
{
break;
}
}
}
}
catch (interprocess_exception& e)
{
break;
}
} while (1);
// stop the gpio monitor if running
if (true == gpioMonEnabled)
{
pthread_cancel(ptidGpio);
}
pthread_exit(NULL);
}
/** @brief Send command line to a threadi */
int sendCmdLine(int i_argc, char** i_argv)
{
int count = 0; // number of arguments sent
using namespace boost::interprocess;
try
{
message_queue mq(open_only, mq_listener);
while (count < i_argc)
{
mq.send(i_argv[count], strlen(i_argv[count]), 0);
count++;
}
// indicate to listener last cmdline arg was sent
mq.send(msg_send_end, strlen(msg_send_end), 0);
}
catch (interprocess_exception& e)
{
count = 0; // assume no arguments sent
}
return count;
}
/** @brief See if the listener thread message queue exists */
bool listenerMqExists()
{
using namespace boost::interprocess;
try
{
message_queue mq(open_only, mq_listener);
return true;
}
catch (interprocess_exception& e)
{
return false;
}
}