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 %d\n",
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);
CodePudding user response:
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());