Can ioctl system calls in linux be interrupted by signals? - linux

since signals are asynchronous in nature there is a chance that it can interrupt a process whenever a process is running in kernel mode or user Mode.
For example, In Robert Love's system programming , read function was done which checks for -EINTR and will restart the system call with remaining bytes to read.
ssize_t ret;
while (len != 0 && (ret = read (fd, buf, len)) != 0) {
if (ret == -1) {
if (errno == EINTR)
continue;
perror ("read");
break;
}
len -= ret;
buf += ret;
}
I came across few ioctl calls from userspace which simply return error by checking the error code < 0. I found similar thing was done in the below link as well.
IOCTL call and checking return value
will same mechanism(checking -EINTR in read call) be needed for other system calls like ioctl? Is is always necessary to check the return code for every system call for -EINTR irrespective of whether my program involves signal handling or not?
I also heard about the automatic restart functionality supported by linux for certain system calls, so drivers return -ERESTARTSYS if corresponding ioctl call fails, but i am not sure ioctl system all will come under this category and will be restarted transparently so userspace donot have to worry about ioctl failure due to signal interruption?
What happens if ioctl was partially executed and signal interrupted in the middle? Is still kernel automatically restart the ioctl call without userspace involvement?

Ioctl is a device driver wilcard call (meaning that the driver is free to implement whatever functionality it wants, sleeping or not), so if it decides to sleep on an event, it decides also if it wants to be interrupted by a kernel interrupt. If it decides not to be interrupted, the kernel will handle the interrupt only after the process wakes up (or will deliver it to another thread that is not in such a state)
Anyway, interrupts are delivered to user process only in user mode, so never the kernel will suspend a system call, to go user mode to execute the user signal handler, then return to kernel mode to end the system call in course. This would break the atomicity of system calls. If the ioctl call sleeps in non-interruptible mode, the signal will have to wait and any handler (or system action in due to the interrupt) will happen after the ioctl call.
In multithreaded environments, a process with multiple threads can receive the interrupt (another, different thread) if one of the threads is in such a situation. The kernel simply delivers the signal to one of the available threads that is able to handle it.

Related

Does read/write blocked system call put the process in TASK_UNINTERRUPTIBLE or TASK_INTERRUPTIBLE state?

As mentioned in the man page of signal(7),
Interruption of system calls and library functions by signal handlers
If a signal handler is invoked while a system call or library function call is blocked, then either:
* the call is automatically restarted after the signal handler returns; or
* the call fails with the error EINTR.
Which of these two behaviors occurs depends on the interface and whether or not the signal handler was established using the SA_RESTART flag (see sigaction(2)). The details vary across UNIX systems; below, the details for
Linux.
If a blocked call to one of the following interfaces is interrupted by a signal handler, then the call will be automatically restarted after the signal handler returns if the SA_RESTART flag was used; otherwise the call will
fail with the error EINTR:
* read(2), readv(2), write(2), writev(2), and ioctl(2) calls on "slow" devices. A "slow" device is one where the I/O call may block for an indefinite time, for example, a terminal, pipe, or socket. If an I/O call on a
slow device has already transferred some data by the time it is interrupted by a signal handler, then the call will return a success status (normally, the number of bytes transferred). Note that a (local) disk is not a
slow device according to this definition; I/O operations on disk devices are not interrupted by signals.
As it is mentioned that a blocked call to one of the following interfaces(read, write) is interrupted by a signal handler, then the call will be automatically restarted after the signal handler returns if the SA_RESTART flag was used, that means in case of blocked read/write system call, process must be in TASK_INTERRUPTIBLE state.
But when I was trying to find out blocked system calls that put process in TASK_UNINTERRUPTIBLE state, I found https://unix.stackexchange.com/questions/62697/why-is-i-o-uninterruptible and Why doing I/O in Linux is uninterruptible? , and in both the places it is mentioned that blocked I/O call(read, write) will put a process in TASK_UNINTERRUPTIBLE.
Also its mentioned here: https://access.redhat.com/sites/default/files/attachments/processstates_20120831.pdf
The Uninterruptible state is mostly used by device drivers waiting for disk or network I/O. When the process
is sleeping uninterruptibly, signals accumulated during the sleep are noticed when the process returns from
the system call or trap. In Linux systems. the command ps -l uses the letter D in the state field (S) to
indicate that the process is in an Uninterruptible sleep state. In that case, the process state flag is set as
follows:
p->state = TASK_UNINTERRUPTABLE
LEARN MORE: Read more about D states in the Red Hat Knowledgebase:
https://access.redhat.com/knowledge/solutions/59989/
It's kind of confusing.
Also I want to know other blocked system calls which can put a process in TASK_UNINTERRUPTIBLE state.
With read(2) or write(2) family syscalls, the type of sleep depends on the type of file that is being accessed. In the documentation you quoted, "slow" devices are those where a read/write will sleep interruptibly, and "fast" devices are those which will sleep uninterruptibly (the uninterruptible sleep state is named D for "Disk Wait", since originally read/write on disk files was the most common reason for this type of sleep).
Note that "blocking" technically refers only to interruptible sleep.
Almost any system call can enter uninterruptible sleep, because this can happen (among other things) when a process needs to acquire a lock protecting an internal kernel resource. Usually, this sort of uninterruptible sleep is so short-lived that you will not notice it.

Delivery of signal to mulitithreaded program with sigmask

If I have a program that has N running threads, and N-1 of them block delivery of the SIGUSR1 signal using pthread_sigmask:
int rc;
sigset_t signal_mask;
sigemptyset(&signal_mask);
sigaddset(&signal_mask, SIGUSR1);
rc = pthread_sigmask(SIG_BLOCK, &signal_mask, NULL);
if (rc != 0) {
// handle error
}
When the OS (Linux, recent kernel) delivers SIGUSR1 to the process, is it guaranteed to be delivered to the unblocked thread? Or could it, for example, try some subset of the blocked threads and then give up?
Yes, it is guaranteed that a process-directed signal will be delivered to one of the threads that has it unblocked (if there are any). The relevant quote from POSIX Signal Generation and Delivery:
Signals generated for the process shall be delivered to exactly one of
those threads within the process which is in a call to a sigwait()
function selecting that signal or has not blocked delivery of the
signal.

Best way to install interrupt handler for port 0x60

I'm writing a simple key logger as a means to understanding interrupts and IO ports for linux drivers. Now from what I've read, I need to register interrupt handlers via ...
int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *dev_name, void *dev_id);
However from what I also read, if I call request_irq during module_init() I will hog the interrupt. My problem is that I want to share the interrupt with other resources but I'm not sure how I can call this interrupt. I wish I could just call the function with module_init() and set my flag to SA_SHIRQ. I am told the best practice is to call during open file which allow for me to set the interrupt, but I don't want to rely on writing a user space program calling open "my_dev" just so that I can run the interrupt handler.
Thanks
Don't worry. request_irq doesn't "hog" the interrupt. It puts the handler on a list of callbacks and calls all handlers (for that IRQ) whenever that interrupt is signaled.
If what you do during the interrupt is heavy lifting, you might want to enable processing IRQs only when the driver is open to minimize system disruption when the driver is not in use. To do that, implement the driver open and close calls, and keep a reference count: only when the ref count > 0 should the ISR be registered
Get it working first, and worry about best practice later. Requesting the IRQ in module_init isn't a big deal - so long as all the resources the interrupt handler needs are available for it to be called immediately...

When and how are system calls interrupted?

This is a followup question to Is a successful send() "atomic"?, as I think it actually concerns system calls in general, not just sends on sockets.
Which system calls can be interrupted, and when they are, where is the interruption handled? I've learned about SA_RESTART, but don't exactly understand what is going on.
If I make a system call without SA_RESTART, can the call be interrupted by any kind of interrupts (e.g. user input) that don't concern my application, but require the OS to abort my call and do something else? Or is it only interrupted by signals that directly concern my process (CTRL+C, socket closed, ...)?
When setting SA_RESTART, what are the semantics of a send() or any other "slow" syscall? Will it always block until all of my data is transmitted or the socket goes down, or can it return with a number smaller than the count in send()'s parameter?
Where is restarting implemented? Does the OS know that I want the call to be restarted upon any interrupts, or is some signal sent to my process and then handled by library code? Or do I have to do it myself, e.g. wrap the call in a while loop and retry as often as necessary?
System calls can be interrupted by any signal, this includes such signals as SIGINT (generated by CTRL-C), SIGHUP, etc.
When SA_RESTART is set, a send() will return (with the sent count) if any data was transmitted before the signal was received, it will return an error EINTR if a send timeout was set (as those can't be restarted), otherwise the send() will be restarted.
System call restarting is implemented in the kernel's signal handling code. The system call internally returns -ERESTARTSYS upon detecting a pending signal (or having a wait interrupted by a signal), which causes the signal handling code to restore the instruction pointer and relevant registers to the state before the call, making the syscall repeat.

Linux kernel interrupt handler mutex protection?

Do I need to protect my interrupt handler being called many times for the same interrupt?
Given the following code, I am not sure on the system calls I should make. I am getting rare, random dead-locks with this current implementation :-
void interrupt_handler(void)
{
down_interruptible(&sem); // or use a lock here ?
clear_intr(); // clear interrupt source on H/W
wake_up_interruptible(...);
up(&sem); // unlock?
return IRQ_HANDLED;
}
void set/clear_intr()
{
spin_lock_irq(&lock);
RMW(x); // set/clear a bit by read/modify/write the H/W interrupt routing register
spin_unlock_irq(&lock);
}
void read()
{
set_intr(); // same as clear_intr, but sets a bit
wait_event_interruptible(...);
}
Should interrupt_handler:down_interruptible be spin_lock_irq / spin_lock_irqsave / local_irq_disable?
Should set/clear_intr:spin_lock_irq be spin_lock_irqsave / local_irq_disable?
Can it (H/W -> kernel -> driver handler) keep generating/getting interrupts until its cleared? Can the interrupt_handler keep getting called while within it?
If as currently implemented the interrupt handler is reentrant then will it block on the down_interruptible?
From LDD3 :-
must be reentrant—it must be capable of running in more than one context at the same time.
Edit 1) after some nice help, suggestions are :-
remove down_interruptible from within interrupt_handler
Move spin_lock_irq outside set/clear methods (no need for spin_lock_irqsave you say?) I really don't see the benefit to this?!
Code :-
void interrupt_handler(void)
{
read_reg(y); // eg of other stuff in the handler
spin_lock_irq(&lock);
clear_intr(); // clear interrupt source on H/W
spin_unlock_irq(&lock);
wake_up_interruptible(...);
return IRQ_HANDLED;
}
void set/clear_intr()
{
RMW(x);
}
void read()
{
error_checks(); // eg of some other stuff in the read method
spin_lock_irq(&lock);
set_intr(); // same as clear_intr, but sets a bit
spin_unlock_irq(&lock);
wait_event_interruptible(...);
// more code here...
}
Edit2) After reading some more SO posts : reading Why kernel code/thread executing in interrupt context cannot sleep? which links to Robert Loves article, I read this :
some interrupt handlers (known in
Linux as fast interrupt handlers) run
with all interrupts on the local
processor disabled. This is done to
ensure that the interrupt handler runs
without interruption, as quickly as
possible. More so, all interrupt
handlers run with their current
interrupt line disabled on all
processors. This ensures that two
interrupt handlers for the same
interrupt line do not run
concurrently. It also prevents device
driver writers from having to handle
recursive interrupts, which complicate
programming.
And I have fast interrupts enabled (SA_INTERRUPT)! So no need for mutex/locks/semaphores/spins/waits/sleeps/etc/etc!
Don't use semaphores in interrupt context, use spin_lock_irqsave instead. quoting LDD3:
If you have a spinlock that can be
taken by code that runs in (hardware
or software) interrupt context, you
must use one of the forms of spin_lock
that disables interrupts. Doing
otherwise can deadlock the system,
sooner or later. If you do not access
your lock in a hardware interrupt
handler, but you do via software
interrupts (in code that runs out of a
tasklet, for example, a topic covered
in Chapter 7), you can use
spin_lock_bh to safely avoid deadlocks
while still allowing hardware
interrupts to be serviced.
As for point 2, make your set_intr and clear_intr require the caller to lock the spinlock, otherwise you'll find your code deadlocking. Again from LDD3:
To make your locking work properly,
you have to write some functions with
the assumption that their caller has
already acquired the relevant lock(s).
Usually, only your internal, static
functions can be written in this way;
functions called from outside must
handle locking explicitly. When you
write internal functions that make
assumptions about locking, do yourself
(and anybody else who works with your
code) a favor and document those
assumptions explicitly. It can be very
hard to come back months later and
figure out whether you need to hold a
lock to call a particular function or
not.
Use spinlock in interrupt context because you don't want to sleep in interrupt context if you didn't acquired a lock.
The code you posted does not look like a device driver irq handler.
The irq handlers in kernel drivers return irqreturn_t and take in int irq_no, void * data as arguements.
You have also not specified if you are registering a threaded handler or a non threaded handler.
A non threaded irq handler cannot have any sleeping calls whether or not you hold any spinlocks.
wait_event, mutex, semaphore, etc, are all sleeping calls and must not be used in a non threaded irq handler. You can however, hold a spinlock to prevent interruption to your interrupt handler. This will ensure that maskable irqs and scheduler do not interrupt your irq handler in the middle.
In a threaded irq handler, such things as sleeping calls (wait queues, mutex, etc) can be used but are still not recommended.

Resources