Re: EINTR vs ERESTARTSYS, ERESTARTSYS not defined

From: Phil Howard (phil-linux-kernel@ipal.net)
Date: Thu Nov 22 2001 - 13:05:42 EST


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

| Phil Howard <phil-linux-kernel@ipal.net> 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/ |
| phil-nospam@ipal.net | Texas, USA | http://phil.ipal.org/     |
-----------------------------------------------------------------
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri Nov 23 2001 - 21:00:31 EST