I am trying to set up a signal and signal handler to rebuffer CAN frames as they arrive. Below is my code. I can send a frame from the computer running this code, but when I send a frame back the other way, nothing happens. I am holding the programme with scanf()
. Can you see why this signal handler is never called?
Admission of guilt: I tailored this code very little from some tutorial. I’ve read the relevent manual pages, but I’m a socket noob.
void my_handler(int const signal_number, siginfo_t *const p_signal_info, void *const p_ucontext) { (void) p_ucontext; printf("Signal with number %d on socket %dn", signal_number, p_signal_info->si_fd); } ... /* At init */ struct sigaction signal_action = {0}; signal_action.sa_sigaction = &my_handler; signal_action.sa_flags = SA_SIGINFO; result = sigaction(SIGRTMIN, &signal_action, NULL); /* On start of comms */ struct ifreq interface_request = {0}; struct sockaddr_can interface_address = {0}; sockets[can_interface_id] = socket(PF_CAN, SOCK_RAW, CAN_RAW); strncpy(interface_request.ifr_name, my_if_name, sizeof(interface_request.ifr_name) - 1); result = ioctl(sockets[can_interface_id], SIOCGIFINDEX, &interface_request); interface_address->can_family = AF_CAN; interface_address->can_ifindex = interface_request.ifr_ifindex; result = bind(sockets[can_interface_id], (struct sockaddr *) &interface_address, sizeof(interface_address)); result = fcntl(sockets[can_interface_id], F_SETSIG, SIGRTMIN); result = fcntl(sockets[can_interface_id], F_GETFL); result = fcntl(sockets[can_interface_id], F_SETFL, result | O_NONBLOCK | O_ASYNC);
Advertisement
Answer
On Linux at least, and perhaps other platforms, F_SETOWN is required for F_SETFL/O_ASYNC to take effect: you must specify the recipient pid of the signal. See, for example, a similar situation in Perl.
For your C code, then, you’d want something like this:
/* _GNU_SOURCE for F_SETSIG */ #define _GNU_SOURCE #include <unistd.h> #include <fcntl.h> .... result = fcntl(sockets[can_interface_id], F_SETSIG, SIGRTMIN); result = fcntl(sockets[can_interface_id], F_GETFL); result = fcntl(sockets[can_interface_id], F_SETFL, result | O_NONBLOCK | O_ASYNC); result = fcntl(sockets[can_interface_id], F_SETOWN, /* <---- */ getpid());