Skip to content

Commit b0d4b26

Browse files
inverter.cpp: avoid mess with simultaneous read/write operations
ned-kelly#77 When many inverter_poller at the same time send commands, the result is undefined. This locks exclusively the configuration file, while the process is running, so that simultaneous instances have to wait until the file is released. For some reason locking the device /dev/hidraw0 does not work for me, I get sometimes the output from previous runs. I suspect that when cInverter::query() does exceed the 2s timeout, it quits, and leaves the response of its commands on the wire. For fd = /dev/hidraw0 tcflush(fd, TCOFLUSH); has no effect. As a matter of fact, on my system I have increased the timeout in cInverter::query() to 15s and now it does always work correctly. Also the program, when called with -1, could exit, while the thread is receiving data, this leaves the next invocation with some ready-data, which it is not expecting.
1 parent d75ab47 commit b0d4b26

File tree

3 files changed

+20
-7
lines changed

3 files changed

+20
-7
lines changed

sources/inverter-cli/inverter.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include <fcntl.h>
22
#include <stdio.h>
33
#include <string.h>
4-
#include <sys/file.h>
54
#include <syslog.h>
65
#include <unistd.h>
76
#include "inverter.h"
@@ -199,7 +198,7 @@ void cInverter::poll() {
199198
ups_qpiws_changed = true;
200199
}
201200
}
202-
201+
if (quit_thread) return;
203202
sleep(5);
204203
}
205204
}

sources/inverter-cli/inverter.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef ___INVERTER_H
22
#define ___INVERTER_H
33

4+
#include <atomic>
45
#include <thread>
56
#include <mutex>
67

@@ -16,6 +17,8 @@ class cInverter {
1617

1718
std::string device;
1819
std::mutex m;
20+
std::thread t1;
21+
std::atomic_bool quit_thread{false};
1922

2023
void SetMode(char newmode);
2124
bool CheckCRC(unsigned char *buff, int len);
@@ -26,8 +29,11 @@ class cInverter {
2629
cInverter(std::string devicename, int qpiri, int qpiws, int qmod, int qpigs);
2730
void poll();
2831
void runMultiThread() {
29-
std::thread t1(&cInverter::poll, this);
30-
t1.detach();
32+
t1 = std::thread(&cInverter::poll, this);
33+
}
34+
void terminateThread() {
35+
quit_thread = true;
36+
t1.join();
3137
}
3238

3339
string *GetQpiriStatus();

sources/inverter-cli/main.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <stdio.h>
99
#include <stdlib.h>
1010
#include <thread>
11+
#include <sys/file.h>
1112

1213
#include "main.h"
1314
#include "tools.h"
@@ -165,13 +166,17 @@ int main(int argc, char* argv[]) {
165166
runOnce = true;
166167
}
167168
lprintf("INVERTER: Debug set");
169+
const char *settings;
168170

169171
// Get the rest of the settings from the conf file
170172
if( access( "./inverter.conf", F_OK ) != -1 ) { // file exists
171-
getSettingsFile("./inverter.conf");
173+
settings = "./inverter.conf";
172174
} else { // file doesn't exist
173-
getSettingsFile("/etc/inverter/inverter.conf");
175+
settings = "/etc/inverter/inverter.conf";
174176
}
177+
getSettingsFile(settings);
178+
int fd = open(settings, O_RDWR);
179+
while (flock(fd, LOCK_EX)) sleep(1);
175180

176181
bool ups_status_changed(false);
177182
ups = new cInverter(devicename,qpiri,qpiws,qmod,qpigs);
@@ -328,6 +333,7 @@ int main(int argc, char* argv[]) {
328333
delete reply2;
329334

330335
if(runOnce) {
336+
ups->terminateThread();
331337
// Do once and exit instead of loop endlessly
332338
lprintf("INVERTER: All queries complete, exiting loop.");
333339
exit(0);
@@ -338,7 +344,9 @@ int main(int argc, char* argv[]) {
338344
sleep(1);
339345
}
340346

341-
if (ups)
347+
if (ups) {
348+
ups->terminateThread();
342349
delete ups;
350+
}
343351
return 0;
344352
}

0 commit comments

Comments
 (0)