fix(PICAN): align socket handling with PIEthernet patterns

- Sentinel: sock = 0 → sock = -1 (0 is stdin, valid fd)
- openDevice(): close socket on ioctl/bind failure (resource leak)
- openDevice(): set O_NONBLOCK via fcntl after socket()
- openDevice(): check setsockopt() return value
- closeDevice(): call shutdown() before close(), reset sock to -1
- readDevice() / writeDevice(): guard against sock == -1
- Add missing #include <fcntl.h>
This commit is contained in:
2026-08-05 17:39:35 +03:00
parent 216109b8ed
commit e89ae88f3a
2 changed files with 19 additions and 4 deletions
+18 -3
View File
@@ -24,6 +24,7 @@
# define PIP_CAN
#endif
#ifdef PIP_CAN
# include <fcntl.h>
# include <linux/can.h>
# include <linux/can/raw.h>
# include <net/if.h>
@@ -49,7 +50,7 @@ PICAN::PICAN(const PIString & path, PIIODevice::DeviceMode mode): PIIODevice(pat
setThreadedReadBufferSize(256);
setPath(path);
can_id = 0;
sock = 0;
sock = -1;
PRIVATE->event.create();
}
@@ -67,19 +68,25 @@ bool PICAN::openDevice() {
sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (sock < 0) {
piCoutObj << "Error! while opening socket";
sock = -1;
return false;
}
fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK);
ifreq ifr;
strcpy(ifr.ifr_name, path().dataAscii());
piCout << "PICAN try to get interface index...";
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
piCoutObj << "Error! while determin the interface ioctl";
::close(sock);
sock = -1;
return false;
}
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof tv);
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof tv) < 0) {
piCoutObj << "Error! while setting socket receive timeout";
}
// bind socket to all CAN interface
sockaddr_can addr;
addr.can_family = AF_CAN;
@@ -87,6 +94,8 @@ bool PICAN::openDevice() {
piCout << "PICAN try to bind socket to interface" << ifr.ifr_ifindex;
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
piCoutObj << "Error! while binding socket";
::close(sock);
sock = -1;
return false;
}
piCout << "PICAN Open OK!";
@@ -101,7 +110,11 @@ bool PICAN::openDevice() {
bool PICAN::closeDevice() {
#ifdef PIP_CAN
interrupt();
if (sock > 0) ::close(sock);
if (sock != -1) {
::shutdown(sock, SHUT_RDWR);
::close(sock);
sock = -1;
}
#endif
return true;
}
@@ -109,6 +122,7 @@ bool PICAN::closeDevice() {
ssize_t PICAN::readDevice(void * read_to, ssize_t max_size) {
#ifdef PIP_CAN
if (sock == -1) return -1;
// piCout << "PICAN read";
can_frame frame;
ssize_t ret = 0;
@@ -127,6 +141,7 @@ ssize_t PICAN::readDevice(void * read_to, ssize_t max_size) {
ssize_t PICAN::writeDevice(const void * data, ssize_t max_size) {
#ifdef PIP_CAN
if (sock == -1) return -1;
// piCout << "PICAN write" << can_id << max_size;
if (max_size > 8) {
piCoutObj << "Can't send CAN frame bigger than 8 bytes (requested " << max_size << ")!";
+1 -1
View File
@@ -73,7 +73,7 @@ protected:
private:
PRIVATE_DECLARATION(PIP_EXPORT)
int sock;
int sock = -1;
int can_id, readed_id;
};