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:
@@ -24,6 +24,7 @@
|
|||||||
# define PIP_CAN
|
# define PIP_CAN
|
||||||
#endif
|
#endif
|
||||||
#ifdef PIP_CAN
|
#ifdef PIP_CAN
|
||||||
|
# include <fcntl.h>
|
||||||
# include <linux/can.h>
|
# include <linux/can.h>
|
||||||
# include <linux/can/raw.h>
|
# include <linux/can/raw.h>
|
||||||
# include <net/if.h>
|
# include <net/if.h>
|
||||||
@@ -49,7 +50,7 @@ PICAN::PICAN(const PIString & path, PIIODevice::DeviceMode mode): PIIODevice(pat
|
|||||||
setThreadedReadBufferSize(256);
|
setThreadedReadBufferSize(256);
|
||||||
setPath(path);
|
setPath(path);
|
||||||
can_id = 0;
|
can_id = 0;
|
||||||
sock = 0;
|
sock = -1;
|
||||||
PRIVATE->event.create();
|
PRIVATE->event.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,19 +68,25 @@ bool PICAN::openDevice() {
|
|||||||
sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||||
if (sock < 0) {
|
if (sock < 0) {
|
||||||
piCoutObj << "Error! while opening socket";
|
piCoutObj << "Error! while opening socket";
|
||||||
|
sock = -1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK);
|
||||||
ifreq ifr;
|
ifreq ifr;
|
||||||
strcpy(ifr.ifr_name, path().dataAscii());
|
strcpy(ifr.ifr_name, path().dataAscii());
|
||||||
piCout << "PICAN try to get interface index...";
|
piCout << "PICAN try to get interface index...";
|
||||||
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
|
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
|
||||||
piCoutObj << "Error! while determin the interface ioctl";
|
piCoutObj << "Error! while determin the interface ioctl";
|
||||||
|
::close(sock);
|
||||||
|
sock = -1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
tv.tv_sec = 1;
|
tv.tv_sec = 1;
|
||||||
tv.tv_usec = 0;
|
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
|
// bind socket to all CAN interface
|
||||||
sockaddr_can addr;
|
sockaddr_can addr;
|
||||||
addr.can_family = AF_CAN;
|
addr.can_family = AF_CAN;
|
||||||
@@ -87,6 +94,8 @@ bool PICAN::openDevice() {
|
|||||||
piCout << "PICAN try to bind socket to interface" << ifr.ifr_ifindex;
|
piCout << "PICAN try to bind socket to interface" << ifr.ifr_ifindex;
|
||||||
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
piCoutObj << "Error! while binding socket";
|
piCoutObj << "Error! while binding socket";
|
||||||
|
::close(sock);
|
||||||
|
sock = -1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
piCout << "PICAN Open OK!";
|
piCout << "PICAN Open OK!";
|
||||||
@@ -101,7 +110,11 @@ bool PICAN::openDevice() {
|
|||||||
bool PICAN::closeDevice() {
|
bool PICAN::closeDevice() {
|
||||||
#ifdef PIP_CAN
|
#ifdef PIP_CAN
|
||||||
interrupt();
|
interrupt();
|
||||||
if (sock > 0) ::close(sock);
|
if (sock != -1) {
|
||||||
|
::shutdown(sock, SHUT_RDWR);
|
||||||
|
::close(sock);
|
||||||
|
sock = -1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -109,6 +122,7 @@ bool PICAN::closeDevice() {
|
|||||||
|
|
||||||
ssize_t PICAN::readDevice(void * read_to, ssize_t max_size) {
|
ssize_t PICAN::readDevice(void * read_to, ssize_t max_size) {
|
||||||
#ifdef PIP_CAN
|
#ifdef PIP_CAN
|
||||||
|
if (sock == -1) return -1;
|
||||||
// piCout << "PICAN read";
|
// piCout << "PICAN read";
|
||||||
can_frame frame;
|
can_frame frame;
|
||||||
ssize_t ret = 0;
|
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) {
|
ssize_t PICAN::writeDevice(const void * data, ssize_t max_size) {
|
||||||
#ifdef PIP_CAN
|
#ifdef PIP_CAN
|
||||||
|
if (sock == -1) return -1;
|
||||||
// piCout << "PICAN write" << can_id << max_size;
|
// piCout << "PICAN write" << can_id << max_size;
|
||||||
if (max_size > 8) {
|
if (max_size > 8) {
|
||||||
piCoutObj << "Can't send CAN frame bigger than 8 bytes (requested " << max_size << ")!";
|
piCoutObj << "Can't send CAN frame bigger than 8 bytes (requested " << max_size << ")!";
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
PRIVATE_DECLARATION(PIP_EXPORT)
|
PRIVATE_DECLARATION(PIP_EXPORT)
|
||||||
int sock;
|
int sock = -1;
|
||||||
int can_id, readed_id;
|
int can_id, readed_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user