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
|
||||
#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 << ")!";
|
||||
|
||||
Reference in New Issue
Block a user