Re: Function: int recv (Socket, Buffer,Length, Flags) is returning with the error number 4
- From: scott@xxxxxxxxxxxxx (Scott Lurndal)
- Date: Wed, 25 Jul 2007 19:27:29 GMT
Rainer Weikusat <rweikusat@xxxxxxxxxxx> writes:
scott@xxxxxxxxxxxxx (Scott Lurndal) writes:
Rainer Weikusat <rweikusat@xxxxxxxxxxx> writes:
Barry Margolin <barmar@xxxxxxxxxxxx> writes:
In article <5g5vu7F3ef7jtU1@xxxxxxxxxxxxxxxxx>,
Ulrich Eckhardt <doomster@xxxxxxxx> 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.
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).
#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).
So you complete it, wait for it, or cancel it.
scott
.
- Follow-Ups:
- Re: Function: int recv (Socket, Buffer,Length, Flags) is returning with the error number 4
- From: Rainer Weikusat
- Re: Function: int recv (Socket, Buffer,Length, Flags) is returning with the error number 4
- From: Rainer Weikusat
- Re: Function: int recv (Socket, Buffer,Length, Flags) is returning with the error number 4
- References:
- Function: int recv (Socket, Buffer,Length, Flags) is returning with the error number 4
- From: monty
- Re: Function: int recv (Socket, Buffer,Length, Flags) is returning with the error number 4
- From: Ulrich Eckhardt
- Re: Function: int recv (Socket, Buffer,Length, Flags) is returning with the error number 4
- From: Barry Margolin
- Re: Function: int recv (Socket, Buffer,Length, Flags) is returning with the error number 4
- From: Rainer Weikusat
- Re: Function: int recv (Socket, Buffer,Length, Flags) is returning with the error number 4
- From: Scott Lurndal
- Function: int recv (Socket, Buffer,Length, Flags) is returning with the error number 4
- Prev by Date: Redirect stdin -> tty, tty -> stdout
- Next by Date: Re: pthread_cancel and cleaning
- Previous by thread: Re: Function: int recv (Socket, Buffer,Length, Flags) is returning with the error number 4
- Next by thread: Re: Function: int recv (Socket, Buffer,Length, Flags) is returning with the error number 4
- Index(es):
Relevant Pages
|
|