This is the mail archive of the
gdb-prs@sourceware.org
mailing list for the GDB project.
Re: gdb/2032: GDB introduces odd behavior with accept() function
- From: Daniel Jacobowitz <drow at false dot org>
- To: nobody at sources dot redhat dot com
- Cc: gdb-prs at sources dot redhat dot com,
- Date: 12 Nov 2005 03:58:03 -0000
- Subject: Re: gdb/2032: GDB introduces odd behavior with accept() function
- Reply-to: Daniel Jacobowitz <drow at false dot org>
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