GDB (API)
/home/stan/gdb/src/gdb/nat/linux-waitpid.c
Go to the documentation of this file.
00001 /* Wrapper implementation for waitpid for GNU/Linux (LWP layer).
00002 
00003    Copyright (C) 2001-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #ifdef GDBSERVER
00021 #include "server.h"
00022 #else
00023 #include "defs.h"
00024 #include "signal.h"
00025 #endif
00026 
00027 #include "nat/linux-nat.h"
00028 #include "nat/linux-waitpid.h"
00029 #include "gdb_wait.h"
00030 
00031 /* Print debugging output based on the format string FORMAT and
00032    its parameters.  */
00033 
00034 static inline void
00035 linux_debug (const char *format, ...)
00036 {
00037 #ifdef GDBSERVER
00038   if (debug_threads)
00039     {
00040       va_list args;
00041       va_start (args, format);
00042       vfprintf (stderr, format, args);
00043       fprintf (stderr, "\n");
00044       va_end (args);
00045     }
00046 #else
00047   /* GDB-specific debugging output.  */
00048 #endif
00049 }
00050 
00051 /* Wrapper function for waitpid which handles EINTR, and emulates
00052    __WALL for systems where that is not available.  */
00053 
00054 int
00055 my_waitpid (int pid, int *status, int flags)
00056 {
00057   int ret, out_errno;
00058 
00059   linux_debug ("my_waitpid (%d, 0x%x)\n", pid, flags);
00060 
00061   if (flags & __WALL)
00062     {
00063       sigset_t block_mask, org_mask, wake_mask;
00064       int wnohang;
00065 
00066       wnohang = (flags & WNOHANG) != 0;
00067       flags &= ~(__WALL | __WCLONE);
00068       flags |= WNOHANG;
00069 
00070       /* Block all signals while here.  This avoids knowing about
00071          LinuxThread's signals.  */
00072       sigfillset (&block_mask);
00073       sigprocmask (SIG_BLOCK, &block_mask, &org_mask);
00074 
00075       /* ... except during the sigsuspend below.  */
00076       sigemptyset (&wake_mask);
00077 
00078       while (1)
00079         {
00080           /* Since all signals are blocked, there's no need to check
00081              for EINTR here.  */
00082           ret = waitpid (pid, status, flags);
00083           out_errno = errno;
00084 
00085           if (ret == -1 && out_errno != ECHILD)
00086             break;
00087           else if (ret > 0)
00088             break;
00089 
00090           if (flags & __WCLONE)
00091             {
00092               /* We've tried both flavors now.  If WNOHANG is set,
00093                  there's nothing else to do, just bail out.  */
00094               if (wnohang)
00095                 break;
00096 
00097               linux_debug ("blocking\n");
00098 
00099               /* Block waiting for signals.  */
00100               sigsuspend (&wake_mask);
00101             }
00102           flags ^= __WCLONE;
00103         }
00104 
00105       sigprocmask (SIG_SETMASK, &org_mask, NULL);
00106     }
00107   else
00108     {
00109       do
00110         ret = waitpid (pid, status, flags);
00111       while (ret == -1 && errno == EINTR);
00112       out_errno = errno;
00113     }
00114 
00115   linux_debug ("my_waitpid (%d, 0x%x): status(%x), %d\n",
00116                pid, flags, status ? *status : -1, ret);
00117 
00118   errno = out_errno;
00119   return ret;
00120 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines