From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22810 invoked by alias); 24 Jun 2004 23:57:32 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 22785 invoked from network); 24 Jun 2004 23:57:29 -0000 Received: from unknown (HELO www-cache.kbnet.net) (81.26.107.28) by sourceware.org with SMTP; 24 Jun 2004 23:57:29 -0000 Received: from meolyon.local ([81.26.104.185]) by www-cache.kbnet.net (8.11.6/8.11.6) with ESMTP id i5ONvQa22003; Fri, 25 Jun 2004 00:57:26 +0100 Received: by meolyon.local (Postfix, from userid 500) id 8231B471FC; Fri, 25 Jun 2004 00:57:40 +0100 (BST) Subject: RFA: fix file descripter mapping for sim_callback->close et al To: gdb-patches@sources.redhat.com Date: Thu, 24 Jun 2004 23:57:00 -0000 Cc: joern.rennecke@superh.com MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-Id: <20040624235740.8231B471FC@meolyon.local> From: amylaar@spamcop.net (Joern Rennecke) X-SW-Source: 2004-06/txt/msg00527.txt.bz2 Now that newlib closes the file handles 0, 1 and 2 when exiting, gdb using the simulator becomes rather unhappy when the program exits, since this closes its standard file descriptors, too. This also causes the simulator to terminate sometimes with signal SIGHUP when run from check-gcc / check-objc, although I haven't been able to reproduce this with a simpler expect script. (Observed on i686-pc-linux-gnu Redhat 7.1 & SuSE 8.1) My test results have been rather random recently because of this problem. sim/common/callback.c already has machinery to re-map file handles, but it seems to be unsure what to do when closing the standard file descriptors - it passes on the close request to the underlying OS, and then pretends the file was not closed. Having just gone through analyzing the expect code for spawning processes, I don't think trying to make some descriptors uncloseable on the target side is a good idea to start with. You want to be able to close them, and re-use them for something else on the target side, and the host shouldn't even notice. One we are at it, we can also provide the infrastructure to support dup properly, i.e. we can have multiple target descriptors mapping to the same host descriptor, and the close is only forwarded to the host when the last target descriptor referring to that host descriptor is closed. This can be implemented quite nicely with circular linked lists; struct host_callback only gets two bytes + alignment larger with this change. 2004-06-25 J"orn Rennecke include/gdb: * callback.h (host_callback_struct): Replace members fdopen and alwaysopen with fd_buddy. sim/common: * callback.c: Changed all users. Index: include/gdb/callback.h =================================================================== RCS file: /cvs/src/src/include/gdb/callback.h,v retrieving revision 1.2 diff -p -r1.2 callback.h *** include/gdb/callback.h 15 Oct 2003 12:28:50 -0000 1.2 --- include/gdb/callback.h 24 Jun 2004 23:27:20 -0000 *************** struct host_callback_struct *** 123,130 **** int last_errno; /* host format */ int fdmap[MAX_CALLBACK_FDS]; ! char fdopen[MAX_CALLBACK_FDS]; ! char alwaysopen[MAX_CALLBACK_FDS]; /* System call numbers. */ CB_TARGET_DEFS_MAP *syscall_map; --- 123,137 ---- int last_errno; /* host format */ int fdmap[MAX_CALLBACK_FDS]; ! /* fd_buddy is used to contruct circular lists of target fds that point to ! the same host fd. A uniquely mapped fd points to itself; for a closed ! one, fd_buddy has the value -1. The host file descriptors for stdin / ! stdout / stderr are never closed by the simulators, so they are put ! in a special fd_buddy circular list which also has MAX_CALLBACK_FDS ! as a member. */ ! /* ??? We don't have a callback entry for dup, although it is trival to ! implement now. */ ! short fd_buddy[MAX_CALLBACK_FDS+1]; /* System call numbers. */ CB_TARGET_DEFS_MAP *syscall_map; Index: sim/common/callback.c =================================================================== RCS file: /cvs/src/src/sim/common/callback.c,v retrieving revision 1.8 diff -p -r1.8 callback.c *** sim/common/callback.c 10 May 2004 16:18:03 -0000 1.8 --- sim/common/callback.c 24 Jun 2004 23:26:25 -0000 *************** fdbad (p, fd) *** 110,116 **** host_callback *p; int fd; { ! if (fd < 0 || fd > MAX_CALLBACK_FDS || !p->fdopen[fd]) { p->last_errno = EINVAL; return -1; --- 110,116 ---- host_callback *p; int fd; { ! if (fd < 0 || fd > MAX_CALLBACK_FDS || p->fd_buddy[fd] < 0) { p->last_errno = EINVAL; return -1; *************** os_close (p, fd) *** 132,144 **** int fd; { int result; result = fdbad (p, fd); if (result) return result; ! result = wrap (p, close (fdmap (p, fd))); ! if (result == 0 && !p->alwaysopen[fd]) ! p->fdopen[fd] = 0; return result; } --- 132,151 ---- int fd; { int result; + int i, next; result = fdbad (p, fd); if (result) return result; ! /* If this file descripter has one or more buddies (originals / ! duplicates from a dup), just remove it from the circular list. */ ! for (i = fd; (next = p->fd_buddy[i]) != fd; ) ! i = next; ! if (fd != i) ! p->fd_buddy[i] = p->fd_buddy[fd]; ! else ! result = wrap (p, close (fdmap (p, fd))); ! p->fd_buddy[fd] = -1; return result; } *************** os_open (p, name, flags) *** 234,240 **** int i; for (i = 0; i < MAX_CALLBACK_FDS; i++) { ! if (!p->fdopen[i]) { int f = open (name, cb_target_to_host_open (p, flags), 0644); if (f < 0) --- 241,247 ---- int i; for (i = 0; i < MAX_CALLBACK_FDS; i++) { ! if (p->fd_buddy[i] < 0) { int f = open (name, cb_target_to_host_open (p, flags), 0644); if (f < 0) *************** os_open (p, name, flags) *** 242,248 **** p->last_errno = errno; return f; } ! p->fdopen[i] = 1; p->fdmap[i] = f; return i; } --- 249,255 ---- p->last_errno = errno; return f; } ! p->fd_buddy[i] = i; p->fdmap[i] = f; return i; } *************** static int *** 428,440 **** os_shutdown (p) host_callback *p; { ! int i; for (i = 0; i < MAX_CALLBACK_FDS; i++) { ! if (p->fdopen[i] && !p->alwaysopen[i]) { close (p->fdmap[i]); - p->fdopen[i] = 0; - } } return 1; } --- 435,465 ---- os_shutdown (p) host_callback *p; { ! int i, next, j; for (i = 0; i < MAX_CALLBACK_FDS; i++) { ! int do_close = 1; ! ! next = p->fd_buddy[i]; ! if (next < 0) ! continue; ! do ! { ! j = next; ! if (j == MAX_CALLBACK_FDS) ! do_close = 0; ! next = p->fd_buddy[j]; ! p->fd_buddy[j] = -1; ! /* At the initial call of os_init, we got -1, 0, 0, 0, ... */ ! if (next < 0) ! { ! do_close = 0; ! break; ! } ! } ! while (j != i); ! if (do_close) close (p->fdmap[i]); } return 1; } *************** os_init (p) *** 449,457 **** for (i = 0; i < 3; i++) { p->fdmap[i] = i; ! p->fdopen[i] = 1; ! p->alwaysopen[i] = 1; } p->syscall_map = cb_init_syscall_map; p->errno_map = cb_init_errno_map; --- 474,483 ---- for (i = 0; i < 3; i++) { p->fdmap[i] = i; ! p->fd_buddy[i] = i - 1; } + p->fd_buddy[0] = MAX_CALLBACK_FDS; + p->fd_buddy[MAX_CALLBACK_FDS] = 2; p->syscall_map = cb_init_syscall_map; p->errno_map = cb_init_errno_map; *************** host_callback default_callback = *** 580,587 **** 0, /* last errno */ { 0, }, /* fdmap */ ! { 0, }, /* fdopen */ ! { 0, }, /* alwaysopen */ 0, /* syscall_map */ 0, /* errno_map */ --- 606,612 ---- 0, /* last errno */ { 0, }, /* fdmap */ ! { -1, }, /* fd_buddy */ 0, /* syscall_map */ 0, /* errno_map */