siposcsaba89 / socketcan-cpp

Simple c++ interface to read/write can sockets
Apache License 2.0
30 stars 16 forks source link

SocketCAN:: Read() -Segmentation fault (core dumped) #2

Open vibnwis opened 3 years ago

vibnwis commented 3 years ago

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';

/*

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?

vibnwis commented 3 years ago

You have an inline comment as below.

tv.tv_usec = m_read_timeout_ms * 1000; // Not init'ing this can cause strange errors

Can you elaborate what strange errors were those, please?

I suspect it is what I am experiencing.

When I succeeded setup the following timeout, it causes reading "CAN2 read error: Resource temporarily unavailable CAN2 - read error ". However, if I did not set the timeout or the setting failed. I got the "segmentation faults". Appreciate your comments, please?

if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)) < 0) { perror("Setting timeout failed"); return STATUS_SOCKET_CREATE_ERROR; }

siposcsaba89 commented 3 years ago

Hi @vibnwis

My open() is slightly different as I use on classic CAN, not FD_CAN. See below.

I think you don't need to change anything, because you can control the can mode by setting the mode parameter of the open function SocketCanStatus open(const std::string & can_interface, int32_t read_timeout_ms = 3, SocketMode mode = MODE_CAN_MTU) , the default value is the classic can.

Why did you implement FDCAN? does it SocketCAN support FDCAN by default?

We used can in FD mode, because there were messages on the canbus which used it. I think it depends on the interface driver if it supports or not.

If you only need CAN classic, what would you change your code or how iyour code would look like?

I don't think one need to change anything, it should work out of the box, if you specify the correct opening mode, see my comment above.

You have an inline comment as below.

tv.tv_usec = m_read_timeout_ms * 1000; // Not init'ing this can cause strange errors

Can you elaborate what strange errors were those, please?

This just means if you do not initialize this variable, than it will get some random value and it will cause error.

Unfortunately, I am not an expert on this topic, this is just a minimal implementation what we needed, to read and write can messages. My implementation based on https://github.com/linux-can/can-utils, especially https://github.com/linux-can/can-utils/blob/master/cansend.c. Here you can find lots of information, and people who understands the protocol much better then I am. Sorry, that I cannot help you more. If I will have time I will try to set up a virtual can and test it.

Best Regards, Csaba