Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Function: int recv (Socket, Buffer,Length, Flags) is returning with the error number 4

239 views
Skip to first unread message

monty

unread,
Jul 18, 2007, 3:35:00 AM7/18/07
to
Hi All,

I am facing a problem when a call made to the socket function recv. It
is returning with the error number 4(EINTR).
When I further analyzed i came to know it is because of the "A signal
interrupted the recv subroutine before any data was available ".
It's not like that every time i am facing this proble. I will
take you through a scenario which will give you a brief idea to
understand the problem:
It's like two servers are running and communicating on a TCP
connection. When a sever send a request to another; a connection will
be opened for that request untill the request is processed.

Server one is firing so many requests in parallel. All is going
fine till here when the parallel requests were around 1200 . Now the
number of parallel requests have got crossed to 1500. And i am getting
the above error only for some requests and not for all .

Even i have handled the error for the error EINTR through a signal
handler thread.

For you information, I am working on AIX 5.3 OS and the application is
written in C++.
Please let me know if you require more information to understand the
problem.
What could be reason for interruption of signal while we are reading
from socket?? or Is it because of some configuration parameter of OS??
or anything else......


Please help me.....

Ulrich Eckhardt

unread,
Jul 18, 2007, 3:55:08 AM7/18/07
to
monty wrote:
> I am facing a problem when a call made to the socket function recv. It
> is returning with the error number 4(EINTR).
> When I further analyzed i came to know it is because of the "A signal
> interrupted the recv subroutine before any data was available ".

If I remember correctly, this just means that while the system call was
under way, your program received (and possibly handled) a signal and
therefore the syscall was aborted without anything being done. Just retry
the recv() and you should be fine.

I'd be interested in the rationale to behave like that, i.e. why EINTR is
provided/used at all, in this context or others.

Uli

Ralf Fassel

unread,
Jul 18, 2007, 4:42:20 AM7/18/07
to
* monty <manishg...@gmail.com>

| I am facing a problem when a call made to the socket function
| recv. It is returning with the error number 4(EINTR).

man recv(2)
...
RETURN VALUE
These calls return the number of bytes received, or -1 if an
error occurred.

You should check errno only if recv returns -1. Is that what you do?
If the _recv_ call returns 4, it has received 4 Bytes.

R'

Barry Margolin

unread,
Jul 18, 2007, 9:17:11 PM7/18/07
to
In article <5g5vu7F...@mid.uni-berlin.de>,
Ulrich Eckhardt <doom...@knuut.de> wrote:

Because the Unix designers didn't want to preserve the kernel state of
an in-progress system call while going back to user mode to invoke the
signal handler.

--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***

Rainer Weikusat

unread,
Jul 19, 2007, 3:43:49 AM7/19/07
to
Barry Margolin <bar...@alum.mit.edu> writes:
> In article <5g5vu7F...@mid.uni-berlin.de>,
> Ulrich Eckhardt <doom...@knuut.de> wrote:
>> monty wrote:
>> > I am facing a problem when a call made to the socket function recv. It
>> > is returning with the error number 4(EINTR).
>> > When I further analyzed i came to know it is because of the "A signal
>> > interrupted the recv subroutine before any data was available ".
>>
>> If I remember correctly, this just means that while the system call was
>> under way, your program received (and possibly handled) a signal and
>> therefore the syscall was aborted without anything being done. Just retry
>> the recv() and you should be fine.
>>
>> I'd be interested in the rationale to behave like that, i.e. why EINTR is
>> provided/used at all, in this context or others.
>
> Because the Unix designers didn't want to preserve the kernel state of
> an in-progress system call while going back to user mode to invoke the
> signal handler.

That's a nice speculation by someone with little clue in kernel
programming. The first thing to note here is that not all system calls
are supposed to be interuptible, but only those who can wait for an
indeterminate amount of time until some external event to happens (eg
read on a file descriptor associated with a regular file is not
interruptible, read on a network socket is). Even those system
calls are only ever interrupted if the application has registered a
handler for the particular signal that 'happened'[*]. If the call
should be interrupted or restarted can be specified by adding
SA_RESTART to the sa_flags member of the struct sigaction used
to establish the handler[**]. If the system call returns with errno
set to EINTR after the handler was run, there was no 'kernel state' to
restore, because the process was blocked waiting for something[***].

The assumption behind this is that if the process handled a signal
while being blocked in the kernel, obviously, 'something of interest'
has happened and the process should be able to react to this something
instead of continuing to block in the kernel.

[*] Unfortunately, libraries handle signals, too. Especially,
the various pthread-implementations distributed with glibc for
Linxu do, meaning, when linking with libpthread on Linux,
EINTRs may start to appear in applications not handling
signals themselves, since the various I/O multiplexing
syscalls (poll, select, etc) are not restartable.

[**] 'signal' is a legacy interface with platform dependent
semantics and eventually, even different semantics on the same
platform, depending on macros being defined during compilation
(Linux/ glibc & _XOPEN_SOURCE).

[***] The exception is 'connect'. If a connect is interrupted
by a signal, it is generally necessary to poll for 'writable'
to wait until the connection has been established.

monty

unread,
Jul 19, 2007, 8:11:28 AM7/19/07
to

hi,

Even after retrying same error i am getting.


Ulrich Eckhardt

unread,
Jul 19, 2007, 8:04:48 AM7/19/07
to
monty wrote:
[recv() / EINTR ]

> Even after retrying same error i am getting.

Did you read Ralf's advise? Can you show how you're using recv()? Are you
sure about the input values? "Doesn't work!" is not a useful error
description.

BTW: don't multipost like you did in c.p.t. and it wasn't exactly on-topic
there anyway.

Uli

Scott Lurndal

unread,
Jul 24, 2007, 8:03:10 PM7/24/07
to
Rainer Weikusat <rwei...@mssgmbh.com> writes:
>Barry Margolin <bar...@alum.mit.edu> writes:
>> In article <5g5vu7F...@mid.uni-berlin.de>,
>> Ulrich Eckhardt <doom...@knuut.de> wrote:
>>> monty wrote:
>>> > I am facing a problem when a call made to the socket function recv. It
>>> > is returning with the error number 4(EINTR).
>>> > When I further analyzed i came to know it is because of the "A signal
>>> > interrupted the recv subroutine before any data was available ".
>>>
>>> If I remember correctly, this just means that while the system call was
>>> under way, your program received (and possibly handled) a signal and
>>> therefore the syscall was aborted without anything being done. Just retry
>>> the recv() and you should be fine.
>>>
>>> I'd be interested in the rationale to behave like that, i.e. why EINTR is
>>> provided/used at all, in this context or others.
>>
>> Because the Unix designers didn't want to preserve the kernel state of
>> an in-progress system call while going back to user mode to invoke the
>> signal handler.
>
>That's a nice speculation by someone with little clue in kernel
>programming. The first thing to note here is that not all system calls

May want to lay off the insults when you have really no clue about
Barry's prior computing experience.

He is correct.


> If the system call returns with errno
>set to EINTR after the handler was run, there was no 'kernel state' to
>restore, because the process was blocked waiting for something[***].

This is clearly incorrect, since the modifications to the struct proc
(et alia) in order to 'block waiting for something' are precisely the
state changes that Barry was referring to.

Note that signals are always delivered at the tail-end of the system
call process (just prior to returning to the application), thus to
deliver a signal prior to completion of the system call (e.g. on an
indefinite wait), one must roll-back the kernel state to that at the
time of the system call.

Having to remember this state while invoking a signal handler is
quite complicated by the fact that the signal handler itself can
make system calls, thus the roll-back and EINTR return.

Note that ERESTART came later than EINTR both from an implementation
and a standards perspective.

scott

Rainer Weikusat

unread,
Jul 25, 2007, 4:45:46 AM7/25/07
to
sc...@slp53.sl.home (Scott Lurndal) writes:
> Rainer Weikusat <rwei...@mssgmbh.com> writes:
>>Barry Margolin <bar...@alum.mit.edu> writes:
>>> In article <5g5vu7F...@mid.uni-berlin.de>,
>>> Ulrich Eckhardt <doom...@knuut.de> wrote:
>>>> monty wrote:
>>>> > I am facing a problem when a call made to the socket function recv. It
>>>> > is returning with the error number 4(EINTR).
>>>> > When I further analyzed i came to know it is because of the "A signal
>>>> > interrupted the recv subroutine before any data was available ".
>>>>
>>>> If I remember correctly, this just means that while the system call was
>>>> under way, your program received (and possibly handled) a signal and
>>>> therefore the syscall was aborted without anything being done. Just retry
>>>> the recv() and you should be fine.
>>>>
>>>> I'd be interested in the rationale to behave like that, i.e. why EINTR is
>>>> provided/used at all, in this context or others.
>>>
>>> Because the Unix designers didn't want to preserve the kernel state of
>>> an in-progress system call while going back to user mode to invoke the
>>> signal handler.
>>
>>That's a nice speculation by someone with little clue in kernel
>>programming. The first thing to note here is that not all system calls
>
> May want to lay off the insults when you have really no clue about
> Barry's prior computing experience.

I was refering to the indirect 'worse is better'-quote. The reason
(some) UNIX(*) system calls are interruptible is because there could
be a reason to interrupt them. One would assume this to be even more
true on early UNIX(*), before 'synchronous I/O multiplexing' was
invented.

A characteristic of earlier Unix systems is that if a process
caught a signal while the process was blocked in a "slow"
system call, the system call was interrupted. The system call
returned an error and errno was set to EINTR. This was done
under the assumption that since a signal occurred and the
process caught it, there is a good chance that something has
happened that should wake up the blocked system call.
[APUE, 1st ed., p. 275]

[...]

>> If the system call returns with errno
>>set to EINTR after the handler was run, there was no 'kernel state' to
>>restore, because the process was blocked waiting for something[***].
>
> This is clearly incorrect, since the modifications to the struct proc
> (et alia) in order to 'block waiting for something' are precisely the
> state changes that Barry was referring to.

To return to user space, the process has to return to user
space.


> Note that signals are always delivered at the tail-end of the system
> call process (just prior to returning to the application),

#include <signal.h>
#include <stdio.h>

static void handler(int unused)
{
puts("something stopped me");
exit(0);
}

int main(void)
{
signal(SIGALRM, handler);
alarm(3);
while (1);
return 0;
}

It follows that this program can never stop, because the SIGALRM
cannot be delivered. It stops, though, at least on Linux 2.6.

> thus to deliver a signal prior to completion of the system call
> (e.g. on an indefinite wait), one must roll-back the kernel state to
> that at the time of the system call.

An example of the opposite (that I happen to have written ;-):

static int wcomplete_wait(struct file *file)
{
wait_queue_t wait;
volatile struct usblp *usblp;
int have_signal, complete, rc;

usblp = file->private_data;

if (!usblp_wcomplete((void *)usblp)) {
if (file->f_flags & O_NONBLOCK) return -EAGAIN;

init_waitqueue_entry(&wait, current);
add_wait_queue((wait_queue_head_t *)&usblp->wait, &wait);

goto check_status;
do {
schedule();

check_status:
set_current_state(TASK_INTERRUPTIBLE);
have_signal = signal_pending(current);
complete = usblp_wcomplete((void *)usblp);
} while (!(complete || have_signal));

set_current_state(TASK_RUNNING);
remove_wait_queue((wait_queue_head_t *)&usblp->wait, &wait);

if (!complete) return -EINTR;
}

rc = usblp->writeurb->status;
return rc;
}
[Linux 2.4 USB printer driver 'with some modifications', caller is
write/ writev]

For a blocking write, this is called after the URB (USB request
buffer) has been submitted to the host controller for transmission.
There isn't even a theoretical possibility of 'rolling this back' (see
OHCI spec).

> Note that ERESTART came later than EINTR both from an implementation
> and a standards perspective.

Quoting UNP again (p. 277): "One of the reasons 4.2BSD introduced the
automatic reastart feature is because sometimes we don't know that the
input or output device is slow".

Rainer Weikusat

unread,
Jul 25, 2007, 4:50:24 AM7/25/07
to
sc...@slp53.sl.home (Scott Lurndal) writes:
> Rainer Weikusat <rwei...@mssgmbh.com> writes:
>>Barry Margolin <bar...@alum.mit.edu> writes:
>>> In article <5g5vu7F...@mid.uni-berlin.de>,
>>> Ulrich Eckhardt <doom...@knuut.de> wrote:
>>>> monty wrote:
>>>> > I am facing a problem when a call made to the socket function recv. It
>>>> > is returning with the error number 4(EINTR).
>>>> > When I further analyzed i came to know it is because of the "A signal
>>>> > interrupted the recv subroutine before any data was available ".
>>>>
>>>> If I remember correctly, this just means that while the system call was
>>>> under way, your program received (and possibly handled) a signal and
>>>> therefore the syscall was aborted without anything being done. Just retry
>>>> the recv() and you should be fine.
>>>>
>>>> I'd be interested in the rationale to behave like that, i.e. why EINTR is
>>>> provided/used at all, in this context or others.
>>>
>>> Because the Unix designers didn't want to preserve the kernel state of
>>> an in-progress system call while going back to user mode to invoke the
>>> signal handler.
>>
>>That's a nice speculation by someone with little clue in kernel
>>programming. The first thing to note here is that not all system calls
>
> May want to lay off the insults when you have really no clue about
> Barry's prior computing experience.

I was refering to the indirect 'worse is better'-quote. The reason


(some) UNIX(*) system calls are interruptible is because there could
be a reason to interrupt them. One would assume this to be even more
true on early UNIX(*), before 'synchronous I/O multiplexing' was
invented.

A characteristic of earlier Unix systems is that if a process
caught a signal while the process was blocked in a "slow"
system call, the system call was interrupted. The system call
returned an error and errno was set to EINTR. This was done
under the assumption that since a signal occurred and the
process caught it, there is a good chance that something has
happened that should wake up the blocked system call.
[APUE, 1st ed., p. 275]

[...]

>> If the system call returns with errno


>>set to EINTR after the handler was run, there was no 'kernel state' to
>>restore, because the process was blocked waiting for something[***].
>
> This is clearly incorrect, since the modifications to the struct proc
> (et alia) in order to 'block waiting for something' are precisely the
> state changes that Barry was referring to.

To return to user space, the process has to return to user
space.


> Note that signals are always delivered at the tail-end of the system
> call process (just prior to returning to the application),

#include <signal.h>
#include <stdio.h>

static void handler(int unused)
{
puts("something stopped me");
exit(0);
}

int main(void)
{
signal(SIGALRM, handler);
alarm(3);
while (1);
return 0;
}

It follows that this program can never stop, because the SIGALRM
cannot be delivered. It stops, though, at least on Linux 2.6.

> thus to deliver a signal prior to completion of the system call


> (e.g. on an indefinite wait), one must roll-back the kernel state to
> that at the time of the system call.

An example of the opposite (that I happen to have written ;-):

> Note that ERESTART came later than EINTR both from an implementation
> and a standards perspective.

Quoting APUE again (p. 277): "One of the reasons 4.2BSD introduced the
automatic restart feature is because sometimes we don't know that the

monty

unread,
Jul 25, 2007, 9:26:02 AM7/25/07
to
On Jul 25, 1:50 pm, Rainer Weikusat <rweiku...@mssgmbh.com> wrote:
> sc...@slp53.sl.home (Scott Lurndal) writes:
> > Rainer Weikusat <rweiku...@mssgmbh.com> writes:
> >>Barry Margolin <bar...@alum.mit.edu> writes:
> >>> In article <5g5vu7F3ef7j...@mid.uni-berlin.de>,
> input or output device is slow".- Hide quoted text -
>
> - Show quoted text -

Hi Guys,

I am a new to the unix and thread programming and the discussion is
going above my understanding; apologies for this.
I have read suggestions from all. But I m unable to implement these
thing on my application.
I have tried recieving the message again $ again but it's going into
the infinte loop i.e. signal has occured at the start of the system
call I guess (like said by scott). He has suggested that "one must
roll-back the kernel state to that at the time of the system call";
Scott Can U please tell me how do i acheive this?

Guys i am in trouble right now and requesting all of you to provide me
a solution to the problem for now. Please tell me which are all the
functions I can use to supress the signal before calling the recv
function.

Thanks....looking forward to get help....

Rainer Weikusat

unread,
Jul 25, 2007, 10:04:16 AM7/25/07
to
monty <manishg...@gmail.com> writes:

[...]

> Guys i am in trouble right now and requesting all of you to provide me
> a solution to the problem for now. Please tell me which are all the
> functions I can use to supress the signal before calling the recv
> function.

Fix the bug in your code. If the situations is a you described it,
either call recv again or install your signal handler with
SA_RESTART. If this doesn't work (as you claim) there is another
problem lurking in there.

Scott Lurndal

unread,
Jul 25, 2007, 3:27:29 PM7/25/07
to

Don't try to teach your grandma to suck eggs, sonny.

>
> A characteristic of earlier Unix systems is that if a process
> caught a signal while the process was blocked in a "slow"
> system call, the system call was interrupted. The system call
> returned an error and errno was set to EINTR. This was done
> under the assumption that since a signal occurred and the
> process caught it, there is a good chance that something has
> happened that should wake up the blocked system call.
> [APUE, 1st ed., p. 275]

Read some kernel code, not APUE, whatever that may be. Consider specifically
what it means from a kernel coding standpoint to "interrupt a system call".


>
>[...]
>
>>> If the system call returns with errno
>>>set to EINTR after the handler was run, there was no 'kernel state' to
>>>restore, because the process was blocked waiting for something[***].
>>
>> This is clearly incorrect, since the modifications to the struct proc
>> (et alia) in order to 'block waiting for something' are precisely the
>> state changes that Barry was referring to.
>
>To return to user space, the process has to return to user
>space.
>
>> Note that signals are always delivered at the tail-end of the system
>> call process (just prior to returning to the application),

My comment was specifically in the context of an interrupted system call. The
kernel can deliver signals at any time to a thread which is currently
executing in user mode (ring 3 on x86, x86_64).

So you complete it, wait for it, or cancel it.

scott

Rainer Weikusat

unread,
Jul 25, 2007, 6:38:26 PM7/25/07
to
sc...@slp53.sl.home (Scott Lurndal) writes:
> Read some kernel code, not APUE, whatever that may be.

If you have something to say (which I doubt), then say it.
Otherwise, shut up.

Rainer Weikusat

unread,
Jul 25, 2007, 7:58:01 PM7/25/07
to
sc...@slp53.sl.home (Scott Lurndal) writes:
> Rainer Weikusat <rwei...@mssgmbh.com> writes:
>>sc...@slp53.sl.home (Scott Lurndal) writes:

[...]


> Read some kernel code, not APUE, whatever that may be. Consider
> specifically what it means from a kernel coding standpoint to
> "interrupt a system call".

This warrants a response of its own: It means nothing. The blocked
process could just be left on its own, happily blocking along. The
'interruption' happens solely because someone took the trouble to
cause an 'out of band' wakeup so that the process can return to
userspace in case there is something it should do instead of
blocking (insofar memory for stack is available). At least for Linux
(someone please supply details for 'other kernels') the 'simple
default' is to not wake up the blocked thread and doing otherwise
requires 'writing the code such that this is possible'.

This does not quite mix with the 'but they just didn't want to write
the code' theory.

Scott Lurndal

unread,
Jul 25, 2007, 8:47:24 PM7/25/07
to
Rainer Weikusat <rwei...@mssgmbh.com> writes:
>sc...@slp53.sl.home (Scott Lurndal) writes:
>> Rainer Weikusat <rwei...@mssgmbh.com> writes:
>>>sc...@slp53.sl.home (Scott Lurndal) writes:
>
>[...]
>
>
>> Read some kernel code, not APUE, whatever that may be. Consider
>> specifically what it means from a kernel coding standpoint to
>> "interrupt a system call".
>
>This warrants a response of its own: It means nothing. The blocked
>process could just be left on its own, happily blocking along. The
>'interruption' happens solely because someone took the trouble to
>cause an 'out of band' wakeup so that the process can return to
>userspace in case there is something it should do instead of
>blocking (insofar memory for stack is available). At least for Linux
>(someone please supply details for 'other kernels') the 'simple
>default' is to not wake up the blocked thread and doing otherwise
>requires 'writing the code such that this is possible'.


I've worked personally on every version of the Unix kernel since
v6, including v32 for the vax, svr3, svr4, svr4mp, es/mp, unixware
and various proprietary unixes, as well as writing the linux kernel
debugger. Trust me, I understand exactly what Barry stated. He was
correct, they didn't want to write the code to transparently interrupt
the system call, maintaining the state, to run the signal handler; so
they allowed for EINTR instead to let the application restart the call.

Even SA_RESTART isn't transparent from the point of the view of the system
call, SA_RESTART simply sees the EINTR on return from system call and
re-invokes the call behind the applications back. This implies that any
system call that can return EINTR must be idempotent to the point at which
it is interrupted.

>
>This does not quite mix with the 'but they just didn't want to write
>the code' theory.

'Remember the state' and 'rollback the state' aren't similar operations.

You're referring to rollback the state which is obvious and necessary. Barry
was referring to 'remember the state, while the signal handler calls some
number of system calls, including perhaps the same system call that was to
be interrupted by the signal, then returning to the interruption point with
no application interaction'.

tschuss,

scott

Rainer Weikusat

unread,
Jul 26, 2007, 6:11:53 AM7/26/07
to
sc...@slp53.sl.home (Scott Lurndal) writes:
> Rainer Weikusat <rwei...@mssgmbh.com> writes:
>>sc...@slp53.sl.home (Scott Lurndal) writes:
>>> Rainer Weikusat <rwei...@mssgmbh.com> writes:
>>>>sc...@slp53.sl.home (Scott Lurndal) writes:
>>
>>[...]
>>
>>> Read some kernel code, not APUE, whatever that may be. Consider
>>> specifically what it means from a kernel coding standpoint to
>>> "interrupt a system call".
>>
>>This warrants a response of its own: It means nothing. The blocked
>>process could just be left on its own, happily blocking along. The
>>'interruption' happens solely because someone took the trouble to
>>cause an 'out of band' wakeup so that the process can return to
>>userspace in case there is something it should do instead of
>>blocking (insofar memory for stack is available). At least for Linux
>>(someone please supply details for 'other kernels') the 'simple
>>default' is to not wake up the blocked thread and doing otherwise
>>requires 'writing the code such that this is possible'.
>
> I've worked personally on every version of the Unix kernel since
> v6, including v32 for the vax, svr3, svr4, svr4mp, es/mp, unixware
> and various proprietary unixes, as well as writing the linux kernel
> debugger.

While this is certainly in impressive list, it does not specifically
relate to the topic.

> Trust me, I understand exactly what Barry stated. He was
> correct, they didn't want to write the code to transparently interrupt
> the system call, maintaining the state, to run the signal handler; so
> they allowed for EINTR instead to let the application restart the
> call.

The only reference I have available which talks about 'what they
wanted' is

http://www.awprofessional.com/bookstore/product.asp?isbn=0201563177&rl=1
(sorry for the ad, but you are certainly the first person I have
encountered not being familiar with the acronym)

and that claims something rather different, namely 'they wanted'
certain system call to be interruptible. Which coincides with
real-world usage of signals, especially SIGALRM. Whenever I use that
together with blocking I/O calls that may sleep for an indeterminate
amount of time than because I want the process to return from the
system call, do something different, and then eventually reenter
it. This would hardly be possible if it just continued and this real
world use of system call interruptions is something that you, Mr
Gabriel (http://www.jwz.org/doc/worse-is-better.html) and Mr Margolin
appear to be unaware of.

This is the direct opposite of the ITS design, which was purposely
built such that system calls appear to be atomic (as if implemented in
hardware), ie they are not supposed to be interruptible and the fact
that they have been interrupted nevertheless is hidden by modifying
the arguments originally passed to the system call accordingly and
then restarting it automatically (a more complete description is
available here
<URL:http://www.linearity.org/bawden/ftp/pclsr.memo.gz>).

Judging from available information, especially taking into account
that interrupted system calls are useful to solve certain problems in
the context of otherwise blocking I/O operations, I still claim that
the interruptions were purposely and that the 'simple' restart facility
was basically added later as a hack working around problems arising
with existing code that had been written under the assumption that
they are actually supposed to be atomic.

If you have any evidence to the contrary, please name it.

> SA_RESTART isn't transparent from the point of the view of the system
> call, SA_RESTART simply sees the EINTR on return from system call and
> re-invokes the call behind the applications back.

For fairly obvious reasons, interruptions are not 'transparent' when
viewed from the perspective of the code implementing them.

>>This does not quite mix with the 'but they just didn't want to write
>>the code' theory.
>
> 'Remember the state' and 'rollback the state' aren't similar operations.
>
> You're referring to rollback the state which is obvious and necessary. Barry
> was referring to 'remember the state, while the signal handler calls some
> number of system calls, including perhaps the same system call that was to
> be interrupted by the signal, then returning to the interruption point with
> no application interaction'.

Actually, both 'remembering the state' and 'rolling the state back'
are way too general terms to meaningfully describe anything except a
highly abstracted 'intent of the code'. Additionally 'the state' has
been used to refer to two completely different things here: 'The state
of a partially completed I/O operation' (which PClsering transparently
handles, while UNIX(*) just informs the user code about the part that
was completed) and 'the sleep/ wakeup mechanism' used to block
processes in the kernel and wake them up again. The first cannot be
'rolled back', because it already had irrevocable side effects (like
sending some data to a remote machine) and the second is not 'rolled
back', but just used the way it is supposed to be used: A condition
arises that should cause the process to run again, hence it is woken
up and runs again. The 32V kernel (TUHS has that online) just did a
'long jump' to a specific place in the 'entering the kernel code',
presumably, because it didn't do dynamic memory allocation in the
kernel. Linux, OTOH, just returns along the normal return path,
undoing anything that may need to be undone (like memory allocations)
on the way.

But there is no technical reason for running signal handlers in the
system call return path, except that this is a natural choice if the
system call is supposed to be interrupted, anyway. It would be as
possible to cause the handler to be called from the scheduler
directly after the process has been selected to actually run again,
using a similar 'call and return' mechanism and put the process to
sleep again afterwards or simpler, make the swtch()/ schedule call
return, determine from there that the 'interesting condition' has not
yet happened and going back to sleep, with all of 'the state' just
left intact. As long as there is enough 'fresh' memory available, none
of the already used needs to be touched.

0 new messages