From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24436 invoked by alias); 27 Jun 2012 01:33:55 -0000 Received: (qmail 24428 invoked by uid 22791); 27 Jun 2012 01:33:54 -0000 X-SWARE-Spam-Status: No, hits=-2.4 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,KHOP_THREADED,MSGID_MULTIPLE_AT,RCVD_IN_DNSWL_LOW,RCVD_IN_HOSTKARMA_NO X-Spam-Check-By: sourceware.org Received: from service87.mimecast.com (HELO service87.mimecast.com) (91.220.42.44) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 27 Jun 2012 01:33:40 +0000 Received: from cam-owa1.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) by service87.mimecast.com; Wed, 27 Jun 2012 02:33:38 +0100 Received: from shawin053 ([10.164.2.89]) by cam-owa1.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.0); Wed, 27 Jun 2012 02:34:25 +0100 From: "Terry Guo" To: Cc: References: <000001cd5338$ded61b20$9c825160$@guo@arm.com> In-Reply-To: <000001cd5338$ded61b20$9c825160$@guo@arm.com> Subject: RE: [PATCH]Fix that GDB will get hang on Windows when using pipe to get stdout and stderr from stub Date: Wed, 27 Jun 2012 01:33:00 -0000 Message-ID: <000501cd5404$fbf210c0$f3d63240$@guo@arm.com> MIME-Version: 1.0 X-MC-Unique: 112062702333801601 Content-Type: text/plain; charset=WINDOWS-1252 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-06/txt/msg00822.txt.bz2 Hi Eli, Can you help to review this proposal? The GDB trunk also has this issue. Thanks. BR, Terry > -----Original Message----- > From: gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] On Behalf Of Terry Guo > Sent: Tuesday, June 26, 2012 9:13 AM > To: gdb-patches@sourceware.org > Cc: eliz@gnu.org; Joey Ye; Matthew Gretton-Dann; 'Pedro Alves'; > daniel.jacobowitz@gmail.com > Subject: [PATCH]Fix that GDB will get hang on Windows when using pipe > to get stdout and stderr from stub >=20 > Hi, >=20 > I noticed a cross-built MINGW arm-none-eabi GDB will get hang on > Windows > when use pipe to get stderr and stdout from stub. The command used to > start > stub in GDB is "target extended-remote | > stub-that-write-stderr-before-stdout". For my case, after send > "$vFlashDone#ea" to stub, GDB get hang. The GDB source show that GDB > will > keep waiting for ACK message from stdout of stub, after send the packet. > Unfortunately my stub will write some kind of log information into > stderr > and this action takes place before stub write ACK message to its stdout. > So > the only pipe is occupied by stderr which is waiting for GDB to consume, > while GDB keep waiting for message from the stdout which hasn't pipe to > use. > We finally end up with a deadlock on pipe between GDB/stderr/stdout. >=20 > The following patch can avoid such deadlock by letting GDB also probe > and > consume stderr when waiting for stdout. Please review and comment. >=20 > The Linux version GDB hasn't such issue. I think it's because we use > different way to handle PIPE as stated in functions pipe_open and > pipe_windows_open. For Linux we have two socketpair kind pipes, one for > stdout and one for stderr. While for windows, we only have one pipe > which is > created by _pipe function. >=20 > BR, > Terry >=20 > 2012-06-25 Terry Guo >=20 > * ser_base (ser_base_read_error_fd): New function. > (do_ser_base_readchar): Poll error file descriptor as well as > standard output. > (generic_readchar): Refactor error handling. >=20 > diff --git a/gdb/ser-base.c b/gdb/ser-base.c > index 368afa6..ee6db54 100644 > --- a/gdb/ser-base.c > +++ b/gdb/ser-base.c > @@ -223,6 +223,63 @@ ser_base_wait_for (struct serial *scb, int timeout) > } > } >=20 > +/* Read any error output we might have. */ > + > +void > +ser_base_read_error_fd (struct serial *scb, int close_fd) > +{ > + if (scb->error_fd !=3D -1) > + { > + ssize_t s; > + char buf[81]; > + > + for (;;) > + { > + char *current; > + char *newline; > + int to_read =3D 80; > + int num_bytes =3D -1; > + > + if (scb->ops->avail) > + num_bytes =3D (scb->ops->avail)(scb, scb->error_fd); > + > + if (num_bytes !=3D -1) > + to_read =3D (num_bytes < to_read) ? num_bytes : to_read; > + > + if (to_read =3D=3D 0) > + break; > + > + s =3D read (scb->error_fd, &buf, to_read); > + if ((s =3D=3D -1) || (s =3D=3D 0 && !close_fd)) > + break; > + > + if (s =3D=3D 0 && close_fd) > + { > + /* End of file. */ > + close (scb->error_fd); > + scb->error_fd =3D -1; > + break; > + } > + > + /* In theory, embedded newlines are not a problem. > + But for MI, we want each output line to have just > + one newline for legibility. So output things > + in newline chunks. */ > + buf[s] =3D '\0'; > + current =3D buf; > + while ((newline =3D strstr (current, "\n")) !=3D NULL) > + { > + *newline =3D '\0'; > + fputs_unfiltered (current, gdb_stderr); > + fputs_unfiltered ("\n", gdb_stderr); > + current =3D newline + 1; > + } > + > + fputs_unfiltered (current, gdb_stderr); > + } > + } > +} > + > /* Read a character with user-specified timeout. TIMEOUT is number of > seconds > to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. > Returns > char if successful. Returns -2 if timeout expired, EOF if line > dropped > @@ -273,6 +330,11 @@ do_ser_base_readchar (struct serial *scb, int > timeout) > status =3D SERIAL_TIMEOUT; > break; > } > + > + /* We also need to check and consume the stderr because it could > + come before the stdout for some stubs. If we just sit and > wait > + for stdout, we would hit a deadlock for that case. */ > + ser_base_read_error_fd (scb, 0); > } >=20 > if (status < 0) > @@ -344,53 +406,7 @@ generic_readchar (struct serial *scb, int timeout, > } > } > /* Read any error output we might have. */ > - if (scb->error_fd !=3D -1) > - { > - ssize_t s; > - char buf[81]; > - > - for (;;) > - { > - char *current; > - char *newline; > - int to_read =3D 80; > - > - int num_bytes =3D -1; > - if (scb->ops->avail) > - num_bytes =3D (scb->ops->avail)(scb, scb->error_fd); > - if (num_bytes !=3D -1) > - to_read =3D (num_bytes < to_read) ? num_bytes : to_read; > - > - if (to_read =3D=3D 0) > - break; > - > - s =3D read (scb->error_fd, &buf, to_read); > - if (s =3D=3D -1) > - break; > - if (s =3D=3D 0) > - { > - /* EOF */ > - close (scb->error_fd); > - scb->error_fd =3D -1; > - break; > - } > - > - /* In theory, embedded newlines are not a problem. > - But for MI, we want each output line to have just > - one newline for legibility. So output things > - in newline chunks. */ > - buf[s] =3D '\0'; > - current =3D buf; > - while ((newline =3D strstr (current, "\n")) !=3D NULL) > - { > - *newline =3D '\0'; > - fputs_unfiltered (current, gdb_stderr); > - fputs_unfiltered ("\n", gdb_stderr); > - current =3D newline + 1; > - } > - fputs_unfiltered (current, gdb_stderr); > - } > - } > + ser_base_read_error_fd (scb, 1); >=20 > reschedule (scb); > return ch; >=20 >=20