Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

From reading the man pages on the 'read()' and 'write()' calls it appears that these calls get interrupted by signals regardless of whether they have to block or not.

In particular, assume

  • a process establishes a handler for some signal.
  • a device is opened ( say a terminal .... ) with the 'O_NONBLOCK' NOT set ( i.e. operating in blocking mode )
  • the process then makes a 'read()' system call to read from the device and as a result executes a kernel control path in kernel-space.
  • while the precess is executing its 'read()' in kernel-space, the signal for which the handler was installed earlier is delivered to that process and its signal handler is invoked.

Reading the man pages and the appropriate sections in SUSv3 'System Interfaces volume (XSH)' one finds that:

i. If a read() is interrupted by a signal before it reads any data ( i.e. it had to block because no data was available ), it returns -1 with 'errno' set to [EINTR].

ii. If a read() is interrupted by a signal after it has successfully read some data ( i.e. it was possible to start servicing the request immediately ), it returns the number of bytes read

Question A):

Am I correct to assume that in either case (block/no block) the delivery and handling of the signal is not entirely transparent to the 'read()'?

Case i. seems understandable since the blocking 'read()' would normally place the process in the 'TASK_INTERRUPTIBLE' state so that when a signal is delivered, the kernel places the process into 'TASK_RUNNING' state.

However when the 'read()' doesn't need to block ( case ii. ) and is processing the request in kernel-space, I would have thought that the arrival of a signal and its handling would be transparent much like the arrival and proper handling of a HW interrupt would be. In particular I would have assumed that upon delivery of the signal, the process would be temporarily placed into USER-MODE to execute its signal handler from which it would return eventually to finish off processing the interrupted 'read()' ( in kernel-space ) so that the 'read()' runs its course to completion after which the process returns back to the point just after the call to 'read()' ( in user-space ), with all of the available bytes read as a result.

But ii. seems to imply that the 'read()' is interrupted, since data is available immediately BUT it returns returns 'some' of the data ( instead of all ).

This brings me to my second ( and final ) question

Question B):

If my assumption under A) is correct, why does the 'read()' get interrupted, even though it does not need to block because there is data available to satisfy the request immediately? In other words, why is the 'read()' not resumed after executing the signal handler, eventually resulting in all of the available data ( which was avialable after all ) to be returned?

share|improve this question

1 Answer 1

up vote 0 down vote accepted

There's an interesting discussion about this in the Unix Philosophy page. Basically, it simplifies the kernel design. I believe *BSD has the option to automatically restart interrupted system calls. But on Linux you have to write a wrapper function to deal with it.

share|improve this answer
    
Thank you Keith for pointing me in the right direction, the Wikipedia link you supplied confirms my earlier hunch that the syscall interruption behaviour has more to do with overall design choices than hard technical necessities or impediments. –  darbehdar Jul 12 '11 at 5:27

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.