1

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);
Walkingbeard
  • 590
  • 5
  • 15
  • 2
    Tip: `printf` is not safe to use in a signal handler – ikegami Jun 09 '22 at 13:59
  • Thanks. I have amended it so that the socket and signal number are saved and printed later. – Walkingbeard Jun 09 '22 at 14:05
  • What happens if you also [F_SETOWN the socket to your own pid](https://stackoverflow.com/a/12654701/132382)? – pilcrow Jun 09 '22 at 14:33
  • @pilcrow It works, is what happens! Thank you muchly! If you would like to add it as an answer, please go ahead, for the kudos. Otherwise I will add it in couple of days. – Walkingbeard Jun 13 '22 at 08:10

1 Answers1

1

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());
pilcrow
  • 56,591
  • 13
  • 94
  • 135