From: Jim Blandy <jimb@zwingli.cygnus.com>
To: Michael Snyder <msnyder@cygnus.com>
Cc: gdb-patches@sources.redhat.com
Subject: RFA: clean up logic in linux_child_wait
Date: Fri, 07 Dec 2001 20:05:00 -0000 [thread overview]
Message-ID: <20011208040632.8D2455E9D8@zwingli.cygnus.com> (raw)
GDB still uses linux-thread.c on the S/390.
I don't think this function's callers actually noticed that it was
returning incorrect values, so this patch can't be tested, but it
wasn't analyzing things correctly.
2001-12-07 Jim Blandy <jimb@redhat.com>
* linux-thread.c (linux_child_wait): Rework logic to return proper
errno values, make it clearer that we've handled all cases, and
not depend on errno being preserved across successful system
calls.
Index: gdb/linux-thread.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/linux-thread.c,v
retrieving revision 1.17
diff -c -r1.17 linux-thread.c
*** gdb/linux-thread.c 2001/06/14 21:03:15 1.17
--- gdb/linux-thread.c 2001/12/08 04:01:45
***************
*** 1256,1306 ****
int
linux_child_wait (int pid, int *rpid, int *status)
{
! int save_errno;
/* Note: inftarg has these inside the loop. */
set_sigint_trap (); /* Causes SIGINT to be passed on to the
attached process. */
set_sigio_trap ();
! errno = save_errno = 0;
for (;;)
{
! errno = 0;
! *rpid = waitpid (pid, status, __WCLONE | WNOHANG);
! save_errno = errno;
if (*rpid > 0)
{
/* Got an event -- break out */
break;
- }
- if (errno == EINTR) /* interrupted by signal, try again */
- {
- continue;
}
! errno = 0;
*rpid = waitpid (pid, status, WNOHANG);
if (*rpid > 0)
{
/* Got an event -- break out */
break;
- }
- if (errno == EINTR)
- {
- continue;
}
! if (errno != 0 && save_errno != 0)
! {
! break;
! }
sigsuspend(&linuxthreads_block_mask);
}
clear_sigio_trap ();
clear_sigint_trap ();
! return errno ? errno : save_errno;
}
--- 1256,1364 ----
int
linux_child_wait (int pid, int *rpid, int *status)
{
! int return_errno = 0;
/* Note: inftarg has these inside the loop. */
set_sigint_trap (); /* Causes SIGINT to be passed on to the
attached process. */
set_sigio_trap ();
! /* On older Linux kernels, there's no way to say "please wait for
! both clones and normal processes." If you specify __WCLONE, you
! get clones; if you don't, you don't. Since you might miss one
! while waiting for the other, the only way to wait for both is to
! wait for SIGCHLD, and then use WNOHANG to see what happened. */
for (;;)
{
! int clone_children_exist;
+ /* Check for clones. */
+ *rpid = waitpid (pid, status, __WCLONE | WNOHANG);
+
if (*rpid > 0)
{
/* Got an event -- break out */
break;
}
+ else if (*rpid < 0)
+ {
+ /* Only when the system call fails can we make any
+ assumptions about errno's value. A successful system
+ call may still set errno to something. */
! if (errno == EINTR)
! /* interrupted by signal, try again */
! continue;
! else if (errno != ECHILD)
! {
! /* Some other error, which we should report to our
! caller. */
! return_errno = errno;
! break;
! }
!
! /* There are no clone children. It's not just that they
! exist but they don't have any status to report yet, since
! we used WNOHANG --- it's that there aren't any. */
! clone_children_exist = 0;
! }
! else
! /* Here *rpid is zero. Some clone children exist, but we used
! WNOHANG and they don't have any interesting status to
! report to us yet. Fall through and check for non-clone
! children. */
! clone_children_exist = 1;
!
! /* We didn't find any clones with interesting status; check for
! non-clones. */
*rpid = waitpid (pid, status, WNOHANG);
+
if (*rpid > 0)
{
/* Got an event -- break out */
break;
}
! else if (*rpid < 0)
! {
! /* Only when the system call fails can we make any
! assumptions about errno's value. A successful system
! call may still set errno to something. */
!
! if (errno == EINTR)
! /* interrupted by signal, try again */
! continue;
! else if (errno != ECHILD)
! {
! /* Some unexpected error, which we should report to our
! caller. */
! return_errno = errno;
! break;
! }
!
! /* There are no non-clone children. If there weren't any
! clone children either, then that's an error condition we
! should report to our caller. */
! if (! clone_children_exist)
! {
! return_errno = ECHILD;
! break;
! }
!
! /* Otherwise, we should block, since there are clone
! children. */
! }
! else
! /* Some non-clone children exist, but we used WNOHANG and they
! don't have any interesting status to report to us yet.
! Fall through and block waiting for SIGCHLD. */
! ;
!
sigsuspend(&linuxthreads_block_mask);
}
clear_sigio_trap ();
clear_sigint_trap ();
! return return_errno;
}
next reply other threads:[~2001-12-08 4:05 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2001-12-07 20:05 Jim Blandy [this message]
2001-12-07 20:13 ` Daniel Jacobowitz
2001-12-08 10:14 ` Jim Blandy
2001-12-08 10:28 ` Daniel Jacobowitz
2001-12-08 19:46 ` Jim Blandy
2001-12-09 10:16 ` Andrew Cagney
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20011208040632.8D2455E9D8@zwingli.cygnus.com \
--to=jimb@zwingli.cygnus.com \
--cc=gdb-patches@sources.redhat.com \
--cc=msnyder@cygnus.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox