1
1
#include " can_transceiver.h"
2
2
3
3
#include < errno.h>
4
+ #include < fcntl.h>
4
5
#include < linux/can.h>
5
6
#include < net/if.h>
6
7
#include < sys/ioctl.h>
@@ -108,11 +109,21 @@ CanTransceiver::~CanTransceiver()
108
109
109
110
void CanTransceiver::receive ()
110
111
{
112
+ int flags = fcntl (sock_desc_, F_GETFL, 0 );
113
+ if (flags == -1 ) {
114
+ std::cerr << " failed to get flags for CAN socket fd" << std::endl;
115
+ }
116
+ // make read() non-blocking so mutex gets released
117
+ flags |= O_NONBLOCK;
118
+ if (fcntl (sock_desc_, F_SETFL, flags) == -1 ) {
119
+ std::cerr << " failed to set flags for CAN socket fd" << std::endl;
120
+ }
111
121
while (!shutdown_flag_) {
112
122
// make sure the lock is acquired and released INSIDE the loop, otherwise send() will never get the lock
113
- std::lock_guard<std::mutex> lock (can_mtx_);
114
- CanFrame frame;
115
- ssize_t bytes_read = read (sock_desc_, &frame, sizeof (CanFrame));
123
+ CanFrame frame;
124
+ std::unique_lock<std::mutex> lock (can_mtx_);
125
+ ssize_t bytes_read = read (sock_desc_, &frame, sizeof (CanFrame));
126
+ lock.unlock ();
116
127
if (bytes_read > 0 ) {
117
128
if (bytes_read != sizeof (CanFrame)) {
118
129
std::cerr << " CAN read error: read " << bytes_read << " B but CAN frames are expected to be "
@@ -121,8 +132,12 @@ void CanTransceiver::receive()
121
132
onNewCanData (frame);
122
133
}
123
134
} else if (bytes_read < 0 ) {
124
- std::cerr << " CAN read error: " << errno << " (" << strerror (errno) // NOLINT(concurrency-mt-unsafe)
125
- << " )" << std::endl;
135
+ if (errno != EAGAIN && errno != EWOULDBLOCK) {
136
+ std::cerr << " CAN read error: " << errno << " (" << strerror (errno) // NOLINT(concurrency-mt-unsafe)
137
+ << " )" << std::endl;
138
+ } else {
139
+ std::this_thread::sleep_for (std::chrono::milliseconds (1 ));
140
+ }
126
141
}
127
142
}
128
143
}
0 commit comments