Improve error handling with separate ICanErrorListener
Error handling highlights:
- moved onError from ICanMessageListener to ICanErrorListener
- added isFatal callback argument to request client disconnect
- don't down interface that's already down
Also:
- don't crash if it's not possible to unregister ICanBus
- don't crash while trying to down interface that failed
- make hidl-utils available to vendor libraries
Bug: 143779011
Test: implemented a VHAL service prototype that communicates with this HAL
Change-Id: I98d054da9da0ead5ef952aebc086e052ac996212
diff --git a/automotive/can/1.0/default/CanSocket.cpp b/automotive/can/1.0/default/CanSocket.cpp
index 4d86de6..ecf4044 100644
--- a/automotive/can/1.0/default/CanSocket.cpp
+++ b/automotive/can/1.0/default/CanSocket.cpp
@@ -61,7 +61,14 @@
CanSocket::~CanSocket() {
mStopReaderThread = true;
- mReaderThread.join();
+
+ /* CanSocket can be brought down as a result of read failure, from the same thread,
+ * so let's just detach and let it finish on its own. */
+ if (mReaderThreadFinished) {
+ mReaderThread.detach();
+ } else {
+ mReaderThread.join();
+ }
}
bool CanSocket::send(const struct canfd_frame& frame) {
@@ -94,6 +101,7 @@
void CanSocket::readerThread() {
LOG(VERBOSE) << "Reader thread started";
+ int errnoCopy = 0;
while (!mStopReaderThread) {
/* The ideal would be to have a blocking read(3) call and interrupt it with shutdown(3).
@@ -130,14 +138,20 @@
}
if (errno == EAGAIN) continue;
- LOG(ERROR) << "Failed to read CAN packet: " << errno;
+ errnoCopy = errno;
+ LOG(ERROR) << "Failed to read CAN packet: " << strerror(errno) << " (" << errno << ")";
break;
}
mReadCallback(frame, ts);
}
- if (!mStopReaderThread) mErrorCallback();
+ bool failed = !mStopReaderThread;
+ auto errCb = mErrorCallback;
+ mReaderThreadFinished = true;
+
+ // Don't access any fields from here, see CanSocket::~CanSocket comment about detached thread
+ if (failed) errCb(errnoCopy);
LOG(VERBOSE) << "Reader thread stopped";
}