gdb/2032: GDB introduces odd behavior with accept() function

Daniel Jacobowitz drow@false.org
Sat Nov 12 03:58:00 GMT 2005


The following reply was made to PR gdb/2032; it has been noted by GNATS.

From: Daniel Jacobowitz <drow@false.org>
To: devin@freeshell.org, kettenis@gnu.org
Cc: gdb-gnats@sources.redhat.com
Subject: Re: gdb/2032: GDB introduces odd behavior with accept() function
Date: Fri, 11 Nov 2005 22:57:38 -0500

 [on i386, probably other places too]
 
 Mark, you wrote some of this code, so I wanted to run this by you.
 
 On Fri, Nov 11, 2005 at 11:30:37PM -0000, devin@freeshell.org wrote:
 > When debugging this test program, interupt it during the accept and
 > type "signal SIGHUP".  fd becomes -512.  Without using gdb, it
 > becomes -1.
 
 The -512 is ERESTARTNOHAND, or one of the other internal error codes.
 It escapes because GDB has cancelled the syscall restart.  Two issues
 here:
 
 - We don't need to cancel the syscall restart in this case.  If the
 target is being resumed at the same PC, whether or not a new signal is
 being delivered, there's no reason not to let the syscall restart.
 Can we conditionalize this on writing a _different_ PC?
 
 - The reason the -512 escapes is that we've cancelled syscall
 restarting, but not fixed up errno.  The Linux kernel always
 fixes the register value for errno when handling syscall restart; I
 think it's reasonable for GDB to do the same thing if orig_eax >= 0.
 Yes, this is a bit of linux-kernel-internals leaking to userspace, but
 that's what we get for being so tricksy...
 
 I think either fix would be ok separately, or both together.  If we're
 changing the PC, probably wherever we're changing it to doesn't care
 what's in %eax right now, so we don't need to clear it.  If we're
 leaving the PC alone, and we do want to cancel the syscall, we'll have
 to frob errno back to EINTR ourselves.
 
 Make some sense?
 
 > #define _XOPEN_SOURCE 600
 > #include <sys/socket.h>
 > #include <sys/types.h>
 > #include <arpa/inet.h>
 > #include <stdio.h>
 > #include <signal.h>
 > 
 > void hangup(int sig) { fprintf(stderr, "SIG=%i\n", sig); }
 > 
 > int main(void)
 >     {
 >     int sockfd = socket(AF_INET, SOCK_STREAM, 0);
 >     struct sockaddr_in addr = {0};
 >     int len = sizeof(addr);
 > 
 >     addr.sin_family = AF_INET;
 >     addr.sin_port = htons(9999);
 >     bind(sockfd, &addr, len);
 >     listen(sockfd,5);
 > 
 >     signal(SIGHUP, hangup);
 > 
 >     int fd;
 >     while(fd = accept(sockfd, &addr, &len))
 >         fprintf(stderr, "FD=%i\n", fd);
 > 
 >     }
 > >How-To-Repeat:
 > 
 > >Fix:
 > 
 > >Release-Note:
 > >Audit-Trail:
 > >Unformatted:
 > 
 
 -- 
 Daniel Jacobowitz
 CodeSourcery, LLC



More information about the Gdb-prs mailing list