2001-11-22 14:36:39

by Phil Howard

[permalink] [raw]
Subject: EINTR vs ERESTARTSYS, ERESTARTSYS not defined

The accept() call does indeed return errno==ERESTARTSYS to user space
when coming back from signal handling, even though other things like
poll() return errno==EINTR. This would not really be a problem except
for this in include/linux/errno.h starting at line 6:

+=============================================================================
| #ifdef __KERNEL__
|
| /* Should never be seen by user programs */
| #define ERESTARTSYS 512
| #define ERESTARTNOINTR 513
| #define ERESTARTNOHAND 514 /* restart if no handler.. */
| #define ENOIOCTLCMD 515 /* No ioctl command */
+=============================================================================

So which way is it _supposed_ to be (so someone can patch things up
to make it consistent):

1. User space should never see ERESTARTSYS from any system call

2. ERESTARTSYS can be seen from system call and is defined somewhere

In user space I have to define __KERNEL__ to get programs to compile
when coded to know about all possible (valid?) values of errno from
system calls. As seen from strace:

+=============================================================================
| [pid 6453] accept(5, 0xbffff908, [16]) = ? ERESTARTSYS (To be restarted)
| [pid 6453] --- SIGALRM (Alarm clock) ---
| [pid 6453] getppid() = 6452
| [pid 6453] gettimeofday({1006439405, 5879}, NULL) = 0
| [pid 6453] setitimer(ITIMER_REAL, {it_interval={0, 0}, it_value={9, 994121}}, NULL) = 0
| [pid 6453] rt_sigreturn(0x5) = -1 EINTR (Interrupted system call)
| [pid 6453] accept(5, 0xbffff908, [16]) = ? ERESTARTSYS (To be restarted)
| [pid 6453] --- SIGALRM (Alarm clock) ---
| [pid 6453] getppid() = 6452
| [pid 6453] gettimeofday({1006439415, 6422}, NULL) = 0
| [pid 6453] setitimer(ITIMER_REAL, {it_interval={0, 0}, it_value={9, 993578}}, NULL) = 0
| [pid 6453] rt_sigreturn(0x5) = -1 EINTR (Interrupted system call)
| [pid 6453] accept(5, 0xbffff908, [16]) = ? ERESTARTSYS (To be restarted)
+=============================================================================

--
-----------------------------------------------------------------
| Phil Howard - KA9WGN | Dallas | http://linuxhomepage.com/ |
| [email protected] | Texas, USA | http://phil.ipal.org/ |
-----------------------------------------------------------------


2001-11-22 15:16:01

by Andreas Schwab

[permalink] [raw]
Subject: Re: EINTR vs ERESTARTSYS, ERESTARTSYS not defined

Phil Howard <[email protected]> writes:

|> The accept() call does indeed return errno==ERESTARTSYS to user space
|> when coming back from signal handling, even though other things like
|> poll() return errno==EINTR. This would not really be a problem except
|> for this in include/linux/errno.h starting at line 6:
|>
|> +=============================================================================
|> | #ifdef __KERNEL__
|> |
|> | /* Should never be seen by user programs */
|> | #define ERESTARTSYS 512
|> | #define ERESTARTNOINTR 513
|> | #define ERESTARTNOHAND 514 /* restart if no handler.. */
|> | #define ENOIOCTLCMD 515 /* No ioctl command */
|> +=============================================================================
|>
|> So which way is it _supposed_ to be (so someone can patch things up
|> to make it consistent):
|>
|> 1. User space should never see ERESTARTSYS from any system call

Yes. The kernel either transforms it to EINTR, or restarts the syscall
when the signal handler returns.

|> 2. ERESTARTSYS can be seen from system call and is defined somewhere
|>
|> In user space I have to define __KERNEL__ to get programs to compile
|> when coded to know about all possible (valid?) values of errno from
|> system calls. As seen from strace:

strace is special here, because it gets more information than the traced
program would get.

|> +=============================================================================
|> | [pid 6453] accept(5, 0xbffff908, [16]) = ? ERESTARTSYS (To be restarted)

At this point the accept syscall hasn't actually finished yet, but rather
suspended to let the program execute the signal handler. As soon as the
signal handler returns the syscall will be restarted.

Andreas.

--
Andreas Schwab "And now for something
[email protected] completely different."
SuSE Labs, SuSE GmbH, Schanz?ckerstr. 10, D-90443 N?rnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5

2001-11-22 15:28:41

by Andi Kleen

[permalink] [raw]
Subject: Re: EINTR vs ERESTARTSYS, ERESTARTSYS not defined

Phil Howard <[email protected]> writes:

> |
> | /* Should never be seen by user programs */

This applies to user programs, but not to strace. Try it: the actual user
program doesn't see them. strace is not a ordinary user program here.


-Andi

2001-11-22 18:06:09

by Phil Howard

[permalink] [raw]
Subject: Re: EINTR vs ERESTARTSYS, ERESTARTSYS not defined

On Thu, Nov 22, 2001 at 04:15:40PM +0100, Andreas Schwab wrote:

| Phil Howard <[email protected]> writes:
|
| |> The accept() call does indeed return errno==ERESTARTSYS to user space
| |> when coming back from signal handling, even though other things like
| |> poll() return errno==EINTR. This would not really be a problem except
| |> for this in include/linux/errno.h starting at line 6:
| |>
| |> +=============================================================================
| |> | #ifdef __KERNEL__
| |> |
| |> | /* Should never be seen by user programs */
| |> | #define ERESTARTSYS 512
| |> | #define ERESTARTNOINTR 513
| |> | #define ERESTARTNOHAND 514 /* restart if no handler.. */
| |> | #define ENOIOCTLCMD 515 /* No ioctl command */
| |> +=============================================================================
| |>
| |> So which way is it _supposed_ to be (so someone can patch things up
| |> to make it consistent):
| |>
| |> 1. User space should never see ERESTARTSYS from any system call
|
| Yes. The kernel either transforms it to EINTR, or restarts the syscall
| when the signal handler returns.

This code periodically quits because sometimes there is an unknown errno.

for (;;) {
memset( arg_sock_addr, 0, * arg_sock_addrlen );
new_fd = accept( arg_sockfd_list[fd_index], arg_sock_addr, arg_sock_addrlen );
if ( new_fd >= 0 ) break;
if ( errno == EINTR ) continue;
if ( errno == ECONNABORTED ) continue;
break;
}
if ( new_fd <= 2 ) {
perror( "daemon_accept: accept" );
if ( fd_count > 1 ) continue;
_exit( 1 ); // not very graceful
}

Then strace showed ERESTARTSYS happening, and when I changed the code to:

for (;;) {
memset( arg_sock_addr, 0, * arg_sock_addrlen );
new_fd = accept( arg_sockfd_list[fd_index], arg_sock_addr, arg_sock_addrlen );
if ( new_fd >= 0 ) break;
if ( errno == EINTR ) continue;
if ( errno == ERESTARTSYS ) continue;
if ( errno == ECONNABORTED ) continue;
break;
}
if ( new_fd <= 2 ) {
perror( "daemon_accept: accept" );
if ( fd_count > 1 ) continue;
_exit( 1 ); // not very graceful
}

it started working solidly. I had to define __KERNEL__ to get it. But I don't
want to leave that in there for portable code.

Could this be an unintended leak of ERESTARTSYS? I take it that what the comments
say is what is intended, and that what I actually get isn't.

--
-----------------------------------------------------------------
| Phil Howard - KA9WGN | Dallas | http://linuxhomepage.com/ |
| [email protected] | Texas, USA | http://phil.ipal.org/ |
-----------------------------------------------------------------

2001-11-26 19:52:31

by Alan

[permalink] [raw]
Subject: Re: EINTR vs ERESTARTSYS, ERESTARTSYS not defined

> In user space I have to define __KERNEL__ to get programs to compile
> when coded to know about all possible (valid?) values of errno from
> system calls. As seen from strace:

Beware of strace data. Record the actual syscall returns in your program.
strace sees restarts, your app doesnt