From patchwork Fri Aug 20 22:40:24 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Maciej W. Rozycki" X-Patchwork-Id: 62324 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id DC64CB6F10 for ; Sat, 21 Aug 2010 08:40:52 +1000 (EST) Received: (qmail 15396 invoked by alias); 20 Aug 2010 22:40:44 -0000 Received: (qmail 15367 invoked by uid 22791); 20 Aug 2010 22:40:42 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 20 Aug 2010 22:40:37 +0000 Received: (qmail 1280 invoked from network); 20 Aug 2010 22:40:34 -0000 Received: from unknown (HELO tp.orcam.me.uk) (macro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 20 Aug 2010 22:40:34 -0000 Date: Fri, 20 Aug 2010 23:40:24 +0100 (BST) From: "Maciej W. Rozycki" To: gcc-patches@gcc.gnu.org cc: Mark Mitchell , gdb-patches@sourceware.org Subject: [committed] GDB/libiberty: Mingw32 remote debug hang on close Message-ID: User-Agent: Alpine 1.10 (DEB 962 2008-03-14) MIME-Version: 1.0 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hi, The change I proposed here: http://gcc.gnu.org/ml/gcc-patches/2009-12/msg01089.html http://gcc.gnu.org/ml/gcc-patches/2010-04/msg01214.html has been reviewed by Mark Mitchell off the list and so I have applied it now. For a reference I'm including the original submission below. Maciej ---------- Forwarded message ---------- Message-ID: Date: Wed, 23 Dec 2009 19:25:13 +0000 (GMT) From: Maciej W. Rozycki To: gcc-patches@gcc.gnu.org Cc: gdb-patches@sourceware.org, Maciej W. Rozycki Subject: [PATCH] GDB/libiberty: Mingw32 remote debug hang on close Hello, Noticed while debugging a remote target using pipes to communicate with a debug stub both running on a Mingw32 host. When a debug session is terminated from the GDB side, like with: (gdb) kill and the stub outputs any data to its stderr file descriptor (such as diagnostic information) afterwards before it terminates, then both programs hang. I have tracked down the cause to be the parent pipe descriptor corresponding to child's stderr having been left open while a wait() call is made in the parent to await child's termination. Meanwhile the child would keep producing diagnostic output to its stderr up till the exhaustion of the pipe system buffer at which point the child would hang as the parent busy with the wait() would not pay attention to its corresponding descriptor anymore. Here's a change that works for me. It makes sure the parent pipe descriptors corresponding to child's stderr and stdout are closed before the call to wait() is made, making any writes to these pipes in the child fail straight away. 2009-12-23 Maciej W. Rozycki libiberty/ * pex-common.c (pex_read_err): Set stderr_pipe to -1 if a corresponding stream has been opened. (pex_free): Close pipe file descriptors corresponding to child's stdout and stderr before waiting. Regression tested successfully with GDB testsuite the i386-mingw32 host and the mips-sde-elf target, using QEMU as the remote system. OK to apply? Maciej gdb-6.8.50-20091205-pex-free-0.patch Index: libiberty/pex-common.c =================================================================== --- libiberty/pex-common.c (revision 268718) +++ libiberty/pex-common.c (working copy) @@ -505,6 +505,7 @@ pex_read_err (struct pex_obj *obj, int b if (o < 0 || o == STDIN_FILE_NO) return NULL; obj->read_err = obj->funcs->fdopenr (obj, o, binary); + obj->stderr_pipe = -1; return obj->read_err; } @@ -597,8 +598,17 @@ pex_get_times (struct pex_obj *obj, int void pex_free (struct pex_obj *obj) { + /* Close pipe file descriptors corresponding to child's stdout and + stderr so that the child does not hang trying to output anything + while we're waiting for it. */ if (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO) obj->funcs->close (obj, obj->next_input); + if (obj->stderr_pipe >= 0 && obj->stderr_pipe != STDIN_FILE_NO) + obj->funcs->close (obj, obj->stderr_pipe); + if (obj->read_output != NULL) + fclose (obj->read_output); + if (obj->read_err != NULL) + fclose (obj->read_err); /* If the caller forgot to wait for the children, we do it here, to avoid zombies. */ @@ -619,10 +629,6 @@ pex_free (struct pex_obj *obj) free (obj->status); if (obj->time != NULL) free (obj->time); - if (obj->read_output != NULL) - fclose (obj->read_output); - if (obj->read_err != NULL) - fclose (obj->read_err); if (obj->remove_count > 0) {