Hello,
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 = os.open(“/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:
pass
Working code using C:
void int_sighandler(int signo)
{
printf(“\n int_sighandler called \n”);
return;
}
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')
counter_file.close()
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:
pass
time.sleep(3)
You can run this program as a root user:
$ sudo python3 file1.py
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.
titusece
(Titus)
June 8, 2022, 10:45am
3
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.