How to receive callbacks in python from kernel interrupts SIGIO

Would like to receive callbacks for receiving interrupts from kernel. I was able to receive interrupts in user space C code with registering the SIGIO with sigaction & fcntl, but not sure how to receive the same way in python. Really appreciate any insights on this.

Not working python code:

import fcntl
import os
import signal

def receiveSignal(signalNumber, frame):
print(‘Received:’, signalNumber)

signal.signal(signal.SIGIO, receiveSignal)

test_fd ="/dev/testDev", os.O_RDWR)
rv = fcntl.fcntl(test_fd, fcntl.F_SETOWN, os.getpid())
rv = fcntl.fcntl(test_fd, fcntl.F_SETFL, fcntl.fcntl(test_fd, fcntl.F_GETFL))

signal.signal(signal.SIGIO, receiveSignal)

while True:

Working code using C:

void int_sighandler(int signo)
printf("\n int_sighandler called \n");
int main(void)

    int test_fd  = open("/dev/testDev", O_RDWR);
    if (test_fd  < 0) {
            printf("[APP] SDM dev open is failed! %d\n", rc);
            return -1;
    struct sigaction action;
    memset(&action, 0, sizeof(action));
    action.sa_handler = int_sighandler;
    action.sa_flags = 0;

    sigaction(SIGIO, &action, NULL);

    fcntl(test_fd , F_SETOWN, getpid());
    fcntl(test_fd , F_SETFL, fcntl(test_fd , F_GETFL) | FASYNC);
  while (1) {}


Most likely, you are facing permission issues since /dev/testDev is owned by root.

$ ls -lh /dev/testDev        
-rw-r--r-- 1 root root 0 Jun  8 10:46 /dev/testDev

When sending signals to that process, you have to act on behalf of the root user by switching to that user:

$ sudo su -

or you can add sudo in front of your command:

$ sudo kill -SIGIO $PID

It also could be that the file doesn’t exist in the first place. To solve this, you can tweak your program to handle this case:

import fcntl
import os
import signal
import time

def receiveSignal(signalNumber, frame):
  print('Received:', signalNumber)

signal.signal(signal.SIGIO, receiveSignal)

test_fn = "/dev/testDev"
if not os.path.exists(test_fn):
   counter_file = open(test_fn, 'w')
test_fd = open(test_fn, "rt+")
fcntl.fcntl(test_fd, fcntl.F_SETOWN, os.getpid())
fcntl.fcntl(test_fd, fcntl.F_SETFL, fcntl.fcntl(test_fd, fcntl.F_GETFL) | fcntl.FASYNC)
print(f"Process ID: {os.getpid()}")

while True:

You can run this program as a root user:

$ sudo python3

Now, the program is listening to a SIGIO signal that would trigger the callback function:

Process ID: 18930

Open up a new terminal session to send that signal:

$ sudo kill -SIGIO 18930

Your program should output:

Received: 29

That’s pretty much it. I hope it helps.

Thanks Mahmoud Harmouch.
Actually I am in root user only when I execute the test. but thanks for your hint, I am using kill_pid() in kernel driver now to send signal to userspace PID and received the signal in python now.