-
Notifications
You must be signed in to change notification settings - Fork 18
Description
Hi there,
I experience "segmentation fault" after the very first read. You can see messages below that it received the first frame, and when reading or in the read(), it failed consistently. I can't see any wrong with it. I have tried all solutions, but still no avails. It would be appreciate if you could share your expertise, please.
CAN2Agent::recv_message() entered
SocketCAN:: Read() - About to read from CAN interface can0
SocketCAN:: Read() - read from CAN interface can0 completed with num_bytes 16
SocketCAN: Read() frame.can_dlc= 8, frame.can_id = 291
data[170]data[1]data[2]data[3]data[4]data[5]data[6]data[7]
SocketCAN: Read() ended
len 8 byte, id: 291 data[0]: aa data[1]: 01 data[2]: 02 data[3]: 03 data[4]: 04 data[5]: 05 data[6]: 06 data[7]: 07
write frame_id to source of input_packet
write frame_len to source of input_packet
write frame_data to source of input_packet
set_data()- len 8
set_data()- ended
CAN2Agent::recv_message() exited
CAN2Agent::recv_message() entered
SocketCAN:: Read() - About to read from CAN interface can0
Segmentation fault (core dumped)
My open() is slightly different as I use on classic CAN, not FD_CAN. See below.
SocketCanStatus SocketCan::open(const std::string & can_interface, int32_t read_timeout_ms, SocketMode mode)
{
m_interface = can_interface;
m_socket_mode = mode;
m_read_timeout_ms = read_timeout_ms;
char buf[100];
/* open socket */
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
{
perror("socketcan ");
return STATUS_SOCKET_CREATE_ERROR;
}
//int enable_canfd = 1; //Lim for time being not supporting CAN_FD
struct ifreq ifr;
strncpy(ifr.ifr_name, can_interface.c_str(), IFNAMSIZ - 1);
ifr.ifr_name[IFNAMSIZ - 1] = '\0';
/*
-
retrieve index of the interface name
/
ifr.ifr_ifindex = if_nametoindex(ifr.ifr_name);
/
* index of the interface name
*/
if (!ifr.ifr_ifindex) {
perror("if_nametoindex");
printf("Interface name %s",ifr.ifr_name);
return STATUS_INTERFACE_NAME_TO_IDX_ERROR;
}/* * retrieve the interface index for the interface name (can0, can1, vcan0 etc) we wish to use. */ if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { perror("SIOCGIFINDEX"); return STATUS_CAN_OP_ERROR; } /* const int timestamping_flags = (SOF_TIMESTAMPING_SOFTWARE | \ SOF_TIMESTAMPING_RX_SOFTWARE | \ SOF_TIMESTAMPING_RAW_HARDWARE); if (setsockopt(m_socket, SOL_SOCKET, SO_TIMESTAMPING, ×tamping_flags, sizeof(timestamping_flags)) < 0) { perror("setsockopt SO_TIMESTAMPING is not supported by your Linux kernel"); } */ /* * The owner - disable default receive filter on this RAW socket * This is obsolete as we do not read from the socket at all, but for * this reason we can remove the receive list in the Kernel to save a * little (really a very little!) CPU usage. * * */ /* #define CAN_SFF_MASK 0x000007FFU / * Standard frame format (SFF) * / #define CAN_EFF_MASK 0x1FFFFFFFU / * Extended frame format (EFF) * / #define CAN_ERR_MASK 0x1FFFFFFFU / * Ignore EFF, RTR, ERR flags * / */ /* 12 Nov 20 Lim - Re-open the default receive filter on this RAW socket */ //setsockopt(m_socket, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0); // Disable frame reception /* * A filter matches, when <received_can_id> & mask == can_id & mask */
#if 0
struct can_filter rfilter[2];
rfilter[0].can_id = 0x128;
rfilter[0].can_mask = CAN_SFF_MASK;
rfilter[1].can_id = 0x120; //x120-x123
rfilter[1].can_mask = 0x1FC; //001-1111-1100 eg, 0x120-0x123
#else
/* accept all frames */
struct can_filter rfilter[1];
rfilter[0].can_id = CAN_SFF_MASK;
rfilter[0].can_mask = 0x123; // can_mask = 0, all frames pass through
#endif
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));
#if 1
struct timeval tv;
tv.tv_sec = 0;
// tv.tv_usec = 1100;
// tv.tv_usec = m_read_timeout_ms * 10; // Not init'ing this can cause strange errors
setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv,sizeof(struct timeval));
printf("\nSocketCAN init interval set %d succeeded\n",tv.tv_usec);
#endif
// LINUX
struct sockaddr_can addr;
memset(&addr, 0, sizeof(addr));
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("Socket CAN2 bind");
return STATUS_BIND_ERROR;
}
sprintf(buf,"%s \n", ifr.ifr_name);
printf("SocketCAN for interface %s succeeded\n",buf);
return STATUS_OK;
}
There is one more thing I puzzle and hopefully you could shed some light as well. It is about
struct timeval tv;
tv.tv_sec = 0;
// tv.tv_usec = 1100;
As soon as I uncomment tv.tv_usec = 1100, it will cause the
auto num_bytes = ::read(s, &frame, int(sizeof(struct can_frame)));
to fail. So now, I keep it commented out.
Also, you can see that the read is somewhat different from yours. i.e auto num_bytes = ::read(m_socket, &frame, CANFD_MTU);
I was wondering does yours read() work?
If you only need CAN classic, what would you change your code or how iyour code would look like?
Why did you implement FDCAN? does it SocketCAN support FDCAN by default?
Very appreciate your comments, please?